JoinPoint
- PointCut 후보
- Advice 가 적용 될 수 있는 메서드
PointCut
- JoinPoint 중에서 실제 Advice를 적용하기 위해 선별해 낸 메서드
- PointCut Expression 을 통해 선별함
Advice
- 선별된 PointCut 메서드에 적용될 횡단기술
Weaving
- Advice를 PointCut
servlet-context.xml
logAdvisor를 빈으로 만들어 놓기
HomeController의 home 메서드(매개변수는 있을수도 없을수도)
pointcut 준비해놓기
before로 적용
aop:before
스프링이 갖고 있는 bean에서만 HttpSession만 Autowired 할 수 있다.
리퀘스트를 출력할 때
셋어트리뷰트 하지 않았으므로 null이 나올 것
before가 먼저 출력 후 메서드 실행
매개변수의 자료형과 개수를 모르기 때문에 오브젝트형 배열로 받는다.
지나가던 request 에 값 넣어놓기
범용성없는 예제코드
가도있던 코드는 낚아채서 추가처리 후 보낼 수 있다.
AOP는 강력하지만 오류도 많이 발생시키기 때문에 사용 패턴이 정해져 있다 (로그 남기기, 트랜젝션, 시큐리티)
aop:around
ProceedingJoinPoint : around 만 가질 수 있는 매개변수
JoinPoint 상속받아 기능을 모두 가짐
낚아챈 시점 (38번 라인)
39번에서 실행된 메서드의 리턴값이 돌아옴
어드바이스가 포인트컷매서드를 콜 한다.
성능체크 시( endtime - starttime ) around 사용 적절
ex. 보드컨트롤러에 있는 모든 메서드 성능체크 하기
모든 메서드에 적용되므로 범용성 있는 코드로 작성 할 것.
package kh.spring.aspect;
import java.text.SimpleDateFormat;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.springframework.beans.factory.annotation.Autowired;
public class LogAdvisor {
@Autowired
private HttpSession session;
// advice
public void aopTest(JoinPoint jp) {
Signature sign = jp.getSignature();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
String currentTime = sdf.format(System.currentTimeMillis());
Object[] args = jp.getArgs();
HttpServletRequest req = (HttpServletRequest)args[0];
req.setAttribute("request", "Hello AOP");
System.out.println("===============");
System.out.println(currentTime);
System.out.println(jp.getTarget()); // Advice가 적용되어 실행되는 메서드의 클래스
System.out.println(sign.getName());
System.out.println("===============");
// System.out.println(session.getAttribute("loginId"));
}
public Object aroundTest(ProceedingJoinPoint pjp) throws Throwable {
long startTime = System.currentTimeMillis();
String returnValue = (String)pjp.proceed();
long endTime = System.currentTimeMillis();
System.out.println(endTime-startTime);
return returnValue;
}
}
controller가 아니라 서비스에도 걸 수 있음
리턴값이 Object인 이유는
리턴값이 void인 경우 default return값으로 null을 리턴한다.
컨트롤러에서 null을 리턴하면 리퀘스트맵핑url의 jsp로 이동 동작
Advice는 return값을 명시하면 null을 리턴
null은 주소자료형으로 int형에 넣을 수 없다.