본문 바로가기

자바/SpringFrameWork

[스프링퀵스타트2-2] : 스프링 AOP-어드바이스의 동작 시점(P. 171 ~ )

3. 어드바이스의 동작 시점

 

" 어드바이스 = 횡단관심 + 횡단관심 동작 시점(* 포인트 컷의 어느시점에 적용을 해야 하는지 ) 이다. 여기서는 횡단관심의 '동작 시점'에 대해서 배워 본다."

" 애스팩트(ASpect) = 어드바이스 + 포인트컷"

 

※ 횡단 관심의 동작 시점

동작시점 설명  엘리먼트(.xml/어노테이션)
Before 포인트 컷 실행 전 동작 <aop:before>
After -After Returning : 포인트 컷이 성공적으로 리턴되면 동작
-After Throwing : 비즈니스 메소드 실행 중 예외 발생 시 동작
-After : 비지니스 메소드가 실행 된 후, 무조건 동작
<aop:after-returning>
<aop:after-throwing>
<aop:after>
Around  Around는 메소드 호출 자체를 가로채 포인트 컷 실행 전후 로직 삽입  <after-round>
* 3.1 이하 모든 어드바이스들은 Client에서 호출 하고 있다.

 

3.1 Before 어드바이스

: 포인트 컷으로 지정 된 메소드 호출 시, 메소드 실행되기 전 처리될 내용들을 기술하기 위해서 사용함. 

 

#첨부자료1. AOP 지정 스프링 설정 파일

<bean id="before" class="com.springbook.biz.common.BeforeAdvice"/>

<aop:config>
	<aop:pointcut id="allPointcut" 
	expression="execution(* com.springbook.biz..*Impl.*(..))"/>
	
	<aop:aspect ref="before"> 
	<aop:before pointcut-ref="allPointcut" method="beforeLog"/>
	</aop:aspect>
</aop:config>

#첨부자료2. 실행 파일

"포인트컷(* insertBoard(), getBoardList()) 실행 전에 횡단메소드가 실행 되고 있는 모습 "

 

3.2 After Returning 어드바이스

: 포인트 컷으로 지정 된 메소드가 정상적으로 실행 되고나서, 메소드 수행 결과로 생성된 데이터를 리턴하는 시점에 동작함

 

#첨부자료1. AOP 지정 스프링 설정 파일

<bean id="afterReturning" class="com.springbook.biz.common.AfterReturningAdvice"/>
<aop:config>
	<aop:pointcut id="getPointcut" 
	expression="execution(* com.springbook.biz..*Impl.*(..))"/>
	
	<aop:aspect ref="afterReturning"> 
	<aop:after-returning pointcut-ref="getPointcut" method="afterLog"/>
	</aop:aspect>
</aop:config>

#첨부자료2. 실행 파일

"포인트컷(* insertBoard(), getBoardList()) 실행 후에 횡단메소드가 실행 되고 있는 모습 "

 

3.3 After Throwing 어드바이스

: 포인트 컷으로 지정된 메소드가 실행 되다가 예외가 발생하는 시점에 동작한다.

(* 예외 발생한 상황은 p177에 표기)

#첨부자료1. AOP 지정 스프링 설정 파일

<bean id="before" class="com.springbook.biz.common.BeforeAdvice"/>
<bean id="afterReturning" class="com.springbook.biz.common.AfterReturningAdvice"/>
<bean id="afterThrowing" class="com.springbook.biz.common.AfterThrowingAdvice"/>
<aop:config>
	<aop:pointcut id="allPointcut" 
	expression="execution(* com.springbook.biz..*Impl.*(..))"/>
	
	<aop:aspect ref="afterThrowing"> 
	<aop:after-throwing pointcut-ref="allPointcut" method="exceptionLog"/>
	</aop:aspect>
</aop:config>

#첨부자료2. 실행 파일

"포인트 컷 상에 예외가 발생하자 해당 시점에 어드바이스가 실행 된 모습"

3.4 After 어드바이스

: 예외 발생 여부에 상관없이 무조건 수행되어야 하는 어드바이스이다.

  (* try - catch - finally 에서 finally 블록)

 

#첨부자료1. AOP 지정 스프링 설정 파일

<bean id="afterThrowing" class="com.springbook.biz.common.AfterThrowingAdvice"/>
<bean id="after" class="com.springbook.biz.common.AfterAdvice"/>
<aop:config>
	<aop:pointcut id="allPointcut" 
	expression="execution(* com.springbook.biz..*Impl.*(..))"/>
	
	<aop:aspect ref="afterThrowing"> 
	<aop:after-throwing pointcut-ref="allPointcut" method="exceptionLog"/>
	</aop:aspect>
	
	<aop:aspect ref="after">
		<aop:after pointcut-ref="allPointcut" method="finallyLog"/>
	</aop:aspect>
</aop:config>

#첨부자료2. 실행 파일

"try - catch - finally 에서 예외가 발생하더라도 어드바이스가 실행되는 모습이다.(finally)"

3.5 Around 어드바이스

: 비지니스 메소드 실행 전과 후에 모두 동작하여 로직을 처리하는 경우이다.

 

#첨부자료1. AOP 지정 스프링 설정 파일

<bean id="userDAO" class="com.springbook.biz.user.impl.UserDAO"></bean>-->
<!-- P172 before -->
<bean id="before" class="com.springbook.biz.common.BeforeAdvice"/>
<bean id="afterReturning" class="com.springbook.biz.common.AfterReturningAdvice"/>
<bean id="afterThrowing" class="com.springbook.biz.common.AfterThrowingAdvice"/>
<bean id="after" class="com.springbook.biz.common.AfterAdvice"/>
<bean id="around" class="com.springbook.biz.common.AroundAdvice"/>
<aop:config>
	<aop:pointcut id="allPointcut" 
	expression="execution(* com.springbook.biz..*Impl.*(..))"/>
	
	<aop:aspect ref="around">
		<aop:around pointcut-ref="allPointcut" method="aroundLog"/>
	</aop:aspect>
</aop:config>

#첨부자료2. 실행 파일

 

4. JoinPoint와 바인드 변수

"앞장에서 실습한것처럼, 단순히 조인포인트 상에 횡단로직을 삽입하는 것은 크게 의미가 없다. 4장에서는 JoinPoint 인터페이스를 제공받아, 비지니스 메소드들(조인포인트들)의 정보를 출력할 것이다."

 

#참고자료 1. Before 어드바이스 횡단로직(바인드변수 추가)

package com.springbook.biz.common;

import org.aspectj.lang.JoinPoint;

public class BeforeAdvice {
	public void beforeLog(JoinPoint jp) {
		String method = jp.getSignature().getName();
		Object[] args = jp.getArgs();
		
		System.out.println("[사전 처리] 비즈니스 로직 수행 전 동작");
		System.out.println("[사전처리]"+ method +"() 메소드 ARGS 정보 :"+args[0].toString());
	}
}

#참고자료 2. 스프링 설정 파일

<bean id="before" class="com.springbook.biz.common.BeforeAdvice"/>
<bean id="afterReturning" class="com.springbook.biz.common.AfterReturningAdvice"/>
<bean id="afterThrowing" class="com.springbook.biz.common.AfterThrowingAdvice"/>
<bean id="after" class="com.springbook.biz.common.AfterAdvice"/>
<bean id="around" class="com.springbook.biz.common.AroundAdvice"/>
<aop:config>
	<aop:pointcut id="allPointcut" 
	expression="execution(* com.springbook.biz..*Impl.*(..))"/>
	
	<aop:aspect ref="before">
		<aop:before pointcut-ref="allPointcut" method="beforeLog"/>
	</aop:aspect>
</aop:config>
</beans>

#참고자료 3. 실행 파일

 

#참고자료 1. AfterReturning어드바이스 횡단로직(바인드 변수/리턴값 수정)

package com.springbook.biz.common;

import org.aspectj.lang.JoinPoint;

import com.springbook.biz.user.UserVO;

public class AfterReturningAdvice {
	public void afterLog(JoinPoint jp, Object returnObj) {
		String method = jp.getSignature().getName();
		if (returnObj instanceof UserVO) {
			UserVO user = (UserVO) returnObj;
			if (user.getRole().equals("ADMIN")) {
				System.out.println(user.getName() + "로그인(Admin");
			}
		}
		System.out.println("[사후처리] 비즈니스 로직 수행 후 동작");
		System.out.println("[사후처리]" + method + "() 메소드 리턴값 : " + returnObj.toString());
	}
}

 

#참고자료 2. 스프링 설정 파일

<bean id="before" class="com.springbook.biz.common.BeforeAdvice"/>
<bean id="afterReturning" class="com.springbook.biz.common.AfterReturningAdvice"/>
<bean id="afterThrowing" class="com.springbook.biz.common.AfterThrowingAdvice"/>
<bean id="after" class="com.springbook.biz.common.AfterAdvice"/>
<bean id="around" class="com.springbook.biz.common.AroundAdvice"/>
<aop:config>
	<aop:pointcut id="getPointcut" 
	expression="execution(* com.springbook.biz..*Impl.*(..))"/>
	
	<aop:aspect ref="afterReturning">
		<aop:after-returning pointcut-ref="getPointcut" method="afterLog"
					returning = "returnObj"/>
	</aop:aspect>
</aop:config>
</beans>

#참고자료 3. 실행 파일

#참고자료 1. AfterThrowing 어드바이스 횡단로직(바인드 변수/리턴값 수정)

package com.springbook.biz.common;

import org.aspectj.lang.JoinPoint;

public class AfterThrowingAdvice {
	public void exceptionLog(JoinPoint jp, Exception exceptObj){
		String method = jp.getSignature().getName();
		
		System.out.println("[예외처리] 비즈니스 로직 수행 중 예외 발생");
		System.out.println("[예외처리]"+method+"()메소드 수행 중 발생 된 예외 메세지 :"+exceptObj.getMessage());
	}
}

#참고자료 2. 스프링 설정 파일

<!-- P172 before -->
<bean id="before" class="com.springbook.biz.common.BeforeAdvice"/>
<bean id="afterReturning" class="com.springbook.biz.common.AfterReturningAdvice"/>
<bean id="afterThrowing" class="com.springbook.biz.common.AfterThrowingAdvice"/>
<bean id="after" class="com.springbook.biz.common.AfterAdvice"/>
<bean id="around" class="com.springbook.biz.common.AroundAdvice"/>
<aop:config>
	<aop:pointcut id="getPointcut" 
	expression="execution(* com.springbook.biz..*Impl.*(..))"/>
	
	<aop:aspect ref="afterThrowing">
		<aop:after-throwing pointcut-ref="getPointcut" method="exceptionLog"
					throwing = "exceptObj"/>
	</aop:aspect>
</aop:config>
</beans>

#참고자료 3. 실행 파일