온 코딩

[Spring] 어노테이션을 활용한 AOP 본문

복습 ARCHIVE/모델별 프로젝트

[Spring] 어노테이션을 활용한 AOP

SummerON 2021. 6. 18. 14:29

xml을 사용할 경우

	<bean id="before" class="com.hhw.biz.common.BeforeAdvice"></bean>
    
	<aop:config>
		<aop:pointcut expression="execution(* com.hhw.biz..*Impl.*(..))" id="allPointcut"/>
		<aop:pointcut expression="execution(* com.hhw.biz..*Impl.get*(..))" id="getPointcut"/>
		<aop:aspect ref="before">
			<aop:around method="beforeLog" pointcut-ref="allPointcut" />
		</aop:aspect>
	</aop:config>

 

 

어노테이션을 활용할 경우 - 어드바이스 파일 내에 생성

: 이때 만들어지는 메서드는 기능로직이 없는 포인트 컷만을 위한 메서드

package com.hhw.biz.common;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Service;

@Service // applicaionContext.xml의 컴포넌트 스캔에서 읽어야 할 서비스
@Aspect  //Pointcut+Advice 가지고 있어야 함
public class BeforeAdvice {

	public BeforeAdvice() {
	}
	
	@Before("allPointcut()") //포인트 컷에 따라 어드바이스 실행
	public void beforeLog(JoinPoint jp){
		String method = jp.getSignature().getName();
		Object[] args = jp.getArgs();
		System.out.println("[사전처리] 비즈니스 로직 수행 전 동작  :  "+method+" / args정보  : "+args[0].toString());
	}
	
	@Pointcut("execution(* com.hhw.biz..*Impl.*(..))")
	public void allPointcut(){}
}

 

 

after-returning 혹은 after-throwing의 경우 바인딩을 지정해야하기 때문에 어노테이션 설정 시 pointcut설정을 이용하여 설정 

package com.hhw.biz.common;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Service;

import com.hhw.biz.board.BoardVO;

@Service
@Aspect
public class AfterReturningAdvice {

	public AfterReturningAdvice() {
		// TODO Auto-generated constructor stub
	}

	@Pointcut("execution(* com.hhw.biz..*Impl.get*(..))")
	public void getPointcut(){}
	
	@AfterReturning(pointcut="getPointcut()", returning="returnObj")
	public void afterLog(JoinPoint jp, Object returnObj){
		String method = jp.getSignature().getName();
		if(returnObj instanceof BoardVO){
			BoardVO board = (BoardVO) returnObj;
			if(board.getContent().equals("contents")){
				System.out.println(board.getTitle()+"내용은 contents");
			}
		}
		System.out.println("[사후로직] 비즈니스 로직 수행 후 동작  :  "+method+"메서드 리턴값"+returnObj.toString());
	}
	
}
package com.hhw.biz.common;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Service;

@Service
@Aspect
public class AfterThrowingAdvice {

	public AfterThrowingAdvice() {
		// TODO Auto-generated constructor stub
	}
	
	@Pointcut("execution(* com.hhw.biz..*Impl.*(..))")
	public void allPointcut(){}	
	
	@AfterThrowing(pointcut="allPointcut()", throwing="exceptionObj")
	public void exceptionLog(JoinPoint jp, Exception exceptionObj){
		
		String method = jp.getSignature().getName();
		System.out.println("[예외처리] 비즈니스 로직 수행 중 예외발생  :  "+method+" / 예외메세지 : "+exceptionObj);
	}

}

 

@Service 어노테이션이 여러 클래스에 들어가 있을 경우, 어노테이션으로 설정 된 어드바이스 메서드들 모두 실행 됨 

@Aspect 어노테이션이 있는 클래스들이 모두 포인트컷을 가지고 있다면 다 aop:aspect로 인식하고 매번 포인트컷을 생성!

 

PointCommon 클래스

: @Aspect를 여러개 사용함으로써 발생되는 포인트 컷 반복선언 문제를 해결하기 위한 클래스 

package com.hhw.biz.common;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class PointcutCommon {

	@Pointcut("execution(* com.hhw.biz..*Impl.*(..))")
	public void allPointcut(){}
	
	@Pointcut("execution(* com.hhw.biz..*Impl.get*(..))")
	public void getPointcut(){}
	
	public PointcutCommon() {
		// TODO Auto-generated constructor stub
	}

}

어드바이스에서 사용법 : 포인트컷 선언 시 pointcut="PointcutCommon.allPointcut()" 클래스 명 써주기~

package com.hhw.biz.common;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Service;

@Service
@Aspect
public class AfterThrowingAdvice {

	public AfterThrowingAdvice() {
		// TODO Auto-generated constructor stub
	}
	
	@AfterThrowing(pointcut="PointcutCommon.allPointcut()", throwing="exceptionObj")
	public void exceptionLog(JoinPoint jp, Exception exceptionObj){
		
		String method = jp.getSignature().getName();
		System.out.println("[예외처리] 비즈니스 로직 수행 중 예외발생  :  "+method+" / 예외메세지 : "+exceptionObj);
	}

}

 주의 : @Aspect 어노테이션을 없애면 안됨!  / 포인트컷 선언부 없애기

Comments