[spring] XML 기반 AOP 설정
AOP 네임스페이스 선언
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
또는
aop
namespace 체크
AOP 관련 엘리먼트
<aop:config>
<aop:pointcut>
XML 설정 파일에 여러 개 정의 할 수 있음
id 속성을 통해서 이름값을 명시
해당 이름으로 어드바이스 설정에서 참조함
<aop:aspect>
애스팩트는 포이트컷과 어드바이스를 결합한 개념
AOP에서 가장 중요한 핵심 개념
<aop:advisor>
직접 어드바이스를 정의하고자 하는 목적이 아니고 외부에서 정의한 어드바이스를 포인트컷과 연결할 목적으로 사용
어드바이스 설정
위치 선정을 잘 해야 한다.
핵심로직의 메소드가 있다. 할 일을 다하면 리턴한다. 예외가 발생할 수 있다.
public method 핵심로직(){
`Before`
…
예외 발생 {
`After throwing`
} finally {
`After`
}
...
return `After Returning`;
}
가로채기 Around
Advice 클래스 생성
구현
public class Advice {
public void log(){
System.out.println("==== log start ======");
System.out.println("==== log end ======");
}
}
login 이 핵심로직
@Override
public UserVO login(String id, String pw) {
UserVO vo = dao.login(id, pw);
String msg = "";
if (vo != null){
msg = context.getMessage("login.success", new String[]{id}, Locale.KOREA);
}else{
msg = context.getMessage("login.fail", new String[]{id}, Locale.KOREA);
}
System.out.println(msg);
return vo;
}
applicationContext 에 bean 추가
<bean id="advice" class="aop.Advice" />
aop namespace 체크
pointcut 생성
pointcut 생성
<aop:config>
<aop:pointcut id="pc"
expression="execution(* user.service.*Service.login(..))" />
</aop:config>
aspect 생성
<bean id="advice" class="aop.Advice" />
<aop:config>
<aop:pointcut id="pc"
expression="execution(* user.service.*Service.login(..))" />
<aop:aspect ref="advice">
</aop:aspect>
</aop:config>
before
aspect
로 엮는다.
<bean id="advice" class="aop.Advice" />
<aop:config>
<aop:pointcut id="pc"
expression="execution(* user.service.*Service.login(..))" />
<aop:aspect ref="advice">
<aop:before method="log" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
위빙
된다 라고 표현한다.
함수 호출
UserService service = (UserService) context.getBean("service");
service.login("admin", "a1234");
출력 결과
==== log start ======
==== log end ======
UserDAO_JDBC
로그인 되었습니다. admin님
출력 위치를 변경한다.
<aop:after-returning method="log" pointcut-ref="pc"/>
출력결과
UserDAO_JDBC
로그인 되었습니다. admin님
==== log start ======
==== log end ======
예외가 발생하면 출력되지 않는다.
after
예외 발생해도 출력되도록 수정
<bean id="advice" class="aop.Advice" />
<aop:config>
<aop:pointcut id="pc"
expression="execution(* user.service.*Service.login(..))" />
<aop:aspect ref="advice">
<aop:after method="log" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
after-throwing
예외 발생시만 찍는 메소드 생성
// 예외가 발생했을 경우에만 동작
public void log_ex(Exception e){
System.out.println("예외 발생 : " + e.getMessage());
}
throwing
을 추가한다.
<aop:after-throwing method="log_ex" pointcut-ref="pc" throwing="e"/>
advice에 있는 이름과 일치해야 한다. e
부가기능에서 핵심로직의 정보를 출력하는 경우
joinpoint
를 사용
public void log(JoinPoint jp){
System.out.println("==== log start ======");
System.out.println("이름: "+jp.getSignature().getName());
System.out.println("==== log end ======");
}
실행결과
==== log start ======
이름: login
==== log end ======
joinpoint
는 항상 첫번째 파라미터로 한다.
public class Advice {
public void log(JoinPoint jp, Object obj){
System.out.println("==== log start ======");
System.out.println("이름: "+jp.getSignature().getName());
System.out.println("결과값: "+ obj);
System.out.println("==== log end ======");
}
// 예외가 발생했을 경우에만 동작
public void log_ex(Exception e){
System.out.println("예외 발생 : " + e.getMessage());
}
}
after-returning
리턴 값을 출력하도록 수정한다.
<aop:config>
<aop:pointcut id="pc"
expression="execution(* user.service.*Service.login(..))" />
<aop:aspect ref="advice">
<aop:after-returning method="log" pointcut-ref="pc" returning="obj"/> <aop:after-throwing method="log_ex" pointcut-ref="pc" throwing="e"/>
</aop:aspect>
</aop:config>
obj
이름을 일치시킨다
출력 결과
UserDAO_JDBC
로그인 되었습니다. admin님
==== log start ======
이름: login
결과값: UserVO [userid=admin, username=관리자, userpwd=a1234, email=admin@multicampus.co.kr, phone=02-1234, address=서울 역삼]
==== log end ======
Around 어드바이스
Advice 클래스에 around 메소드 생성
public void around(){
System.out.println(" == around start == ");
System.out.println(" == around end == ");
}
가로채기 기능을 한다.
<aop:around method="around" pointcut-ref="pc"/>
출력결과
== around start ==
== around end ==
원래의 메소드가 수행되지 않았다.
재호출 시켜줘야 핵심로직이 돌아간다.
ProceedingJoinPoint
가 반드시 필요하다.
가로챘기 때문에 결과값을 리턴하는 역할까지 해야 한다. 결과값을 가공할 수 있다.
public Object around(ProceedingJoinPoint pp) throws Throwable{
System.out.println(" == around start == ");
Object obj = pp.proceed();
System.out.println(" == around end == ");
return obj;
}
실행결과
== around start ==
UserDAO_JDBC
로그인 되었습니다. admin님
== around end ==
around 성능테스트에 사용가능 하다.
엮어주는 것이 aspect
AOP는 런타임
에 결정된다. proxy 가 동작한다.
Advice 매개변수
export 프로젝트 : https://goo.gl/eFQkI4
'Programming > Spring' 카테고리의 다른 글
[spring] 다국어 지원 (0) | 2016.04.22 |
---|---|
[spring] Annotation 기반 AOP 설정 (0) | 2016.04.22 |
[spring] AOP (Aspect Oriented Programming) (0) | 2016.04.21 |
[spring] Annotation 기반 설정 (0) | 2016.04.20 |
[spring] DI 관련 Source 내용 (0) | 2016.04.20 |
댓글