1. xml 작성
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context">
<!-- 스프링에서는 모든 설정을 setting xml에서 처리함 -->
<bean id="target" class="spring.aop.entity.NewlecExam" p:kor="101" p:eng="1" p:math="1" p:com="1"/>
<bean id="logAroundAdvice" class="spring.aop.advice.LogAroundAdvice"/>
<bean id="logBeforeAdvice" class="spring.aop.advice.LogBeforeAdvice"/>
<bean id="logAfterReturningAdvice" class="spring.aop.advice.LogAfterReturningAdvice"/>
<bean id="logAfterThrowingAdvice" class="spring.aop.advice.LogAfterThrowingAdvice"/>
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 앞의 target은 setTarget을 의미, 뒤 ref의 target은 위의 target빈을 의미 -->
<!-- 프록시에서 인터페이스는 스프링이 자동으로 처리해주기 때문에 target이랑 핸들러(interceptorNAmes란 이름으로)만 주입해주면된다. -->
<property name="target" ref="target"/>
<property name="interceptorNames">
<list>
<!-- Around는 주 기능 앞뒤에 수행 -->
<!-- Before는 다른 기능에 앞서 먼저 수행 -->
<!-- AfterReturning은 앞선 주기능을 수행하는 함수(invocation.proceed(), method.invoke()등)가 반환된 후 나중 수행 -->
<!-- 메소드 실행 도중 예외가 발생하면 AfterReturning이 아닌 AfterThrowing이 실행된다. -->
<value>logAroundAdvice</value>
<value>logBeforeAdvice</value>
<value>logAfterReturningAdvice</value>
<value>logAfterThrowingAdvice</value>
</list>
</property>
</bean>
</beans>
xml에 사용할 어드바이스들의 객체를 생성하고,이를 proxy 핸들러에 주입해준다.
2. 핸들러 클래스 작성
1) Before Advice
public class LogBeforeAdvice implements MethodBeforeAdvice{
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
// TODO Auto-generated method stub
System.out.println("앞에서 실행될 로직");
}
}
주기능을 수행하는 메소드(invocation.proceed(), method.invoke()등)가 실행되기 전에 수행된다.
2) AfterReturning Advice
public class LogAfterReturningAdvice implements AfterReturningAdvice{
// 필요하면 반환 값도 사용할 수 있다.
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
// TODO Auto-generated method stub
System.out.println("returnValue:"+returnValue+", method:"+method.getName());
}
}
주기능을 수행하는 메소드(invocation.proceed(), method.invoke()등)가 실행되어 반환된 후에 수행된다.
3) AfterThrowing Advice
public class LogAfterThrowingAdvice implements ThrowsAdvice{
public void afterThrowing(IllegalArgumentException e) throws Throwable{
System.out.println("예외가 발생하였습니다.: " +e.getMessage());
}
}
주기능을 수행하는 메소드(invocation.proceed(), method.invoke()등)가 실행중 예외 발생시 수행된다.
3. 실행 결과
0) 실행 코드
public class NewlecExam implements Exam{
...
@Override
public int total() {
int result = kor+eng+math+com;
if(kor>100)
throw new IllegalArgumentException("유효하지 않은 국어점수");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
@Override
public float avg() {
float result=total()/4.0f;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
}
public class Program {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/aop/setting.xml");
Exam proxy = (Exam) context.getBean("proxy");
System.out.printf("total is %d\n", proxy.total());
System.out.printf("avg is %f\n", proxy.avg());
}
}
1) 예외가 발생하지 않은 경우(국어 점수 100 이하)
2) 예외가 발생한 경우(국어 점수 100 초과)