advice마다 메서드명이 다를 수 있다
joinpoint는 around에서는 필수
다른 advice들은 필수가 아님
다형성을 사용하려면 누구나 사용하는 기법 : 바인딩 기법
e.g. 챔피언이라는 깡통안에 가렌, 티모를 넣음
이걸 가능하게 하는게 OOP의 다형성
Object returnObj : 바인딩변수
실제 output이 뭐였든 간에 (멤버였는 보드였든) 컨테이너가 Obj에 넣어줌
스프링컨테이너가 보드빈이든 멤버빈이든
Obj라는 깡통안에 넣어줌
<bean id="afterReturningAdvice" class="com.spring.biz.common.AfterReturning"/>
<aop:config>
<aop:aspect ref="afterReturningAdvice">
<aop:after-returning method="afterReturningPrintLog" pointcut-ref="aPointcut" returning="returnObj"/>
</aop:aspect>
</aop:config>
package com.spring.biz.common;
import org.aspectj.lang.JoinPoint;
import com.spring.biz.member.MemberVO;
public class AfterReturning {
// pjp는 jp를 상속받은 객체
// pjp는 aroundAdvie에서는 필수
// 다른 advice들은 필수가 아님
// 비즈니스 메서드의 정보를 받고싶을때 jp를 사용
// 나와 결합될 메서드의 output이 무엇인지 확실 하지 않음 == object사용
public void afterReturningPrintLog(JoinPoint jp, Object returnObj) {//비즈니스의 output이 들어옴
String methodName=jp.getSignature().getName();
// 비즈니스 메서드의 이름
// 현재 해당 어드바이스와 결합된 비즈니스 메서드
System.out.println("횡단관심 : "+methodName+"의 반환 이후의 로그");
// returnObj가 관리자라면, 로그에 [관리자 입장]이라고 출력하고 싶음
if(returnObj instanceof MemberVO) {//returnObj가 member라는 확신이 없음 : instanceof
MemberVO mVO = (MemberVO)returnObj;
if(mVO.getRole().equals("ADMIN")) {
System.out.println("[관리자입장]");
}
else System.out.println("[사용자입장]");
}
else System.out.println("[데이터열람]");//보드나 리스트였겠죠
}
}
===============================================================
AOP를 어노테이션으로 처리할게 라고 하는 설정
<aop:aspectj-autoproxy>
package com.spring.biz.common;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;
@Service
@Aspect
public class AroundAdvice {
@Pointcut("execution(* com.spring.biz..*Imple.*(..))")
public void aPointcut() {}
@Pointcut("execution(* com.spring.biz..*Imple.select*(..))")
public void bPointcut() {}
@Around("bPointcut")
public Object aroundPrintLog(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around 로그 전");//메서드수행 전 출력
///////시작!
StopWatch sw = new StopWatch(); //stopwatch는 스프링에서 제공 해 줌
sw.start();
Object obj=pjp.proceed(); //메서드들을 실행
// 외부의 비즈니스 메서드를 호출함
//obj에다 메서드 실행 결과 값 저장
///////끝!
sw.stop();
String methodName=pjp.getSignature().getName();
System.out.println(methodName+"메서드를 수행하는데에 소요한 시간은"+sw.getTotalTimeMillis()+"초입니다.");
System.out.println("around 로그 후");//메서드수행 후 출력
return obj;//obj에 저장된 반환값을 반환
}
}
Advice.java에 포인트컷에대한 정보를 알려줌
- body를 작성하지 않음
Advice를 new하는 코드 : @Component를 상속받은 @Service를 씀
:service를 쓴 ㄴ이유는 이 친구들이 결합되는 레이어가 Service라서
같은층에서 동일의 어노테이션을 쓰면 더 빨라짐
- 메모리관리가 더 유리함
@Component쓰면 아무 레이어에서 나 스캔
@Aspect걸어주기