Advice - 언제 어떤 공통 관심 사항(보조 업무, cross-cutting concern)을
적용할지 결정하는 방법
Before Advice, After Advice, Around Advice 등이 있다.
Before Advice - 보조 업무가 주 업무 실행 전에 수행되는 경우
After Advice - 보조 업무가 주 업무 실행 후에 수행되는 경우
Around Advice - 보조 업무가 주 업무 실행 전과 후에 수행되는 경우
After Throwing Advice
: 주 업무 실행 과정에서 예외가 발생하였을 때 보조 업무가 수행되는 경우
joinpoint
: Advice 가 적용되는 지점
pointcut
: joinpoint 를 좀 더 세부적으로 적용하기 위해서 joinpoint를 잘라내는 개념
weaving
: 주 업무에 보조 업무를 결합시키는 행위 ( 또는 그 과정)
Spring AOP 에서는 메소드 단위까지만 pointcut을 지원한다.
→ 우리가 지금까지 실습하면서 적용한 건 Around Advice 였다.
주 업무가 실행되기 전의 보조업무
이전 실습 자료를 기반으로 하면
package com.test.spr;
import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.MethodBeforeAdvice;
public class CalculatorBeforeAdvice implements MethodBeforeAdvice
//이걸 상속받았으므로 xml에 등록하면 알아서 주업무시행전에 수행되도록 약속되어있다.
{
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable
{
Log log = LogFactory.getLog(this.getClass());
log.info("Before Advice 실행 ----------------");
log.info("주 업무 실행 전에 수행되어야 하는 업무");
log.info("Before Advice 실행 ---------------");
}
}
위와같은 MethodBeforeAdvice를 implements하는 .java파일을 하나 만든후
설정 정보 (XML)에서
<!-- 추가 -->
<!-- →SpringApp07 의 내용과 비교하여 추가되는 코드 -->
<!-- CalculatorBeforeAdvice 클래스의 객체 정보 전달 -->
<bean id="before" class="com.test.spr.CalculatorBeforeAdvice"></bean>
추가후
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
이 ProxyFactoryBean안에서
<!-- 보조 업무 클래스의 객체 정보 전달-->
<!-- 『interceptorNames』 -->
<property name="interceptorNames">
<list>
<!-- aspect는 Around Advice에 속한다. -->
<value>aspect</value>
<!-- 추가~!!! -->
<!-- → SpringApp07의 내용과 비교하여 추가되는 코드 -->
<!-- Before Advice -->
<value>before</value> beforeAdvice 객체를 추가하면 된다.
이와같이 beforeAdvice 객체 생성후 보조업무 list에 넣으면 된다. before 객체가 MethodBeforeAdvice를 상속받았으므로 Spring이 이를 인식하여 정해진 약속대로 before Advice로써 설정한다.
주 업무 실행중 오류가 생겼을경우 실행될 보조업무이다.
이전 실습 자료를 기반으로 하면
/*================================
CalculatorAfterThrowing.java
- After Throwing Advice 구성
===============================*/
package com.test.spr;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.ThrowsAdvice;
public class CalculatorAfterThrowing implements ThrowsAdvice
{
public void afterThrowing(IllegalArgumentException e)throws Throwable
{
System.out.println(e.toString()); //과 같은 처리가 가능
Log log = LogFactory.getLog(this.getClass());
log.info("After Throwing Advice 실행==========================");
log.info("주 업무 실행 과정에서 예외 발생 시 처리되는 사후 업무");
log.info("After Throwing Advice 실행==========================");
}
}
위와같은 ThrowsAdvice를 implements하는 java파일을 만든후
주 업무 클래스에서
package com.test.spr;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StopWatch;
public class CalculatorImpl implements Calculator
{
// 인터페이스로부터 상속받은 메소드 재정의를 통해
// 주 업무(core concern) 진행(수행)을 위한 메소드 구현
@Override
public int add(int x, int y)
{
// 반환할 결과값
int result = 0;
//※ 주 업무(core concern) 처리 과정에서 예외가 발생할 수 있는 상황을 만들기 위해
// 예외 객체를 생성하여 처리할 수 있도록 구성.
// -try ~ catch ~ finally : 예외 발생시 자체적으로 처리
// -throws : 예외 발생 시 호출한 객체에 예외를 던지는(넘기는)처리
// -throw : 의도적으로 예외를 발생시키는 처리
if(x>100 || y>100)
{
throw new IllegalArgumentException("100보다 큰 인자를 전달한 예외 발생");
}
// 주 엄무(core concern) 실행 내용
result = x + y;
System.out.printf("%d + %d = %d\n", x, y, result);
// 최종 결과값 반환
return result;
}
위와같이 throw new IllegalArgumentException을 하여 예외를 던지면 된다
또한
XML에서
<!-- 추가! -->
<!-- SpringApp08 의 내용과 비교하여 추가되는 초드 -->
<bean id="afterThrowing" class="com.test.spr.CalculatorAfterThrowing"></bean>
<!-- 이와같이 after throwing advice 객체를 추가하고 -->
<!-- 보조업무 list에 넣기-->
<!-- 보조 업무 클래스의 객체 정보 전달-->
<!-- 『interceptorNames』 -->
<property name="interceptorNames">
<list>
<!-- aspect는 Around Advice에 속한다. -->
<value>aspect</value>
<!-- 추가~!!! -->
<!-- → SpringApp07의 내용과 비교하여 추가되는 코드 -->
<!-- Before Advice -->
<value>before</value>
<!-- 추가~!! -->
<!-- SpringApp08의 내용과 비교하여 추가되는 코드 -->
<value>afterThrowing</value>