Spring) @AspectJ 어노테이션을 이용한 AOP 지원
본문 바로가기
programming/Spring & WEB

Spring) @AspectJ 어노테이션을 이용한 AOP 지원

by 코딩하는 핑가 2021. 1. 26.
반응형

* 이 포스팅은 shlee0882.tistory.com/206의 포스팅과 www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte:fdl:aop:aspectj 을 학습한 뒤 추가로 공부한 후 재정리한 글입니다.

* 해당 개념을 완벽하게 이해하지 못해 설명이 다소 미흡할 수 있습니다. 참고만 해주세요.

* 2차 가공 및 재배포를 금지합니다. ( 재배포시 출처를 남겨주세요 )

* 오탈자 및 잘못된 내용은 댓글달아주세요.

 

[ 이전 글 ] AOP 개념 및 설정 + 예제

 

1. Advice를 정의하는 태그

* <aop:before>

- 메서드 실행 전에 적용되는 어드바이스를 정의

 

* <aop:after-returning>

- 메서드가 정상적으로 실행된 후에 적용되는 어드바이스를 정의

 

* <aop:after-throwing>

- 메서드가 예외를 발생시킬 때 적용되는 어드바이스를 정의

- try-catch 블록에서 catch 블록과 비슷

 

* <aop:after>

- 메서드가 정상적으로 실행되는지 또는 예외를 발생시키는지 여부에 상관없이 어드바이스를 정의

- try-catch-finally에서 finally 블록과 비슷

 

* <aop:around>

- 메서드 호출 이전, 이후, 예외발생 등 모든 시점에 적용 가능한 어드바이스를 정의

 

2. JoinPoint 인터페이스

- JoinPoint는 Spring AOP 혹은 AspectJ에서 AOP가 적용되는 지점을 뜻함

- 해당 지점을 AspectJ에서 JoinPoint라는 인터페이스로 나타냄

 

* JoinPoint 메소드

- getArgs() : 메소드 아규먼트를 반환

- getThis() : 프록시 객체를 반환

- getTarget() : 대상 객체를 반환

- getSignature() : 어드바이즈 또는 메소드의 설명을 반환

- toString() : 어드바이즈되는 메소드의 설명을 출력

 

3. Aspect 실행 시점을 지정할 수 있는 어노테이션(@)

* @Aspect

- 이 클래스가 Aspect를 나타내는 클래스라는 것을 명시

 

* @Around

- Advice가 Target 메소드를 감싸서 Target 메소드 호출 전과 후에 실행되는 Advice

- ProceedingJoinPoint의 proceed()를 수행하는데, proceed()의 리턴 값이 sub 메서드의 리턴 값이다.

- 즉 @Advice 내부에서 결과값을 제어

 

* @Before- 어드바이스 타겟 메소드가 호출되기 전에 어드바이스 기능을 수행

 

* @After- 타겟 메소드의 결과에 관계없이(즉 성공, 예외 관계없이) 타겟 메소드가 완료되면 어드바이스 기능을 수행

 

* @AfterReturning- (정상적 반환 이후) 타겟 메소드가 성공적으로 결과값을 반환 후에 어드바이스 기능을 수행

 

* @AfterThrowing- (예외 발생 이후) 타겟 메소드가 수행 중 예외를 던지게 되면 어드바이스 기능을 수행

 

2. 소스코드

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/* Aspect 생성 */
@Aspect
public class AopTEST {
	
    // 타겟 메소드가 실행된 시간을 측정하기 위한 로직을 구현
	@Around("execution(* com.test.TEST*.*(..))")
	public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{
		long begin = System.currentTimeMillis();
		Object retVal = pjp.proceed();
		System.out.println(System.currentTimeMillis() - begin);
		return retVal;
	}
	
	/* 결합점을 지정하여 Advice가  언제 실행될지를 지정하는데 사용 -> 빈의 메소드 실행점을 지정하는 것 
	 * com.test 패키지 하위의 TEST 시작하는 클래스의 모든 세소드 수행과 일치할 targerMethod라는 이름의 pointcut을 정의*/
	@Pointcut("execution(public * com.test.TEST*.*(..))")
	public void targetMethod(){
		// pointcut annotation 값을 참조하기 위한 dummy method		
		
	}

	/* advice 정의 
	 * advice는 aspect의 실제 구현체로 포인트컷 표현식과 일치하는 결합점에 삽입되어 동작할 수 있는 코드 */
	/* beforeTargetMethod() 메소드는 targetMethod()로 정의된 포인트컷 전에 수행 */
	@Before("targetMethod()")
	public void beforeTargetMethod(JoinPoint thisJoinPoint){
		Class clazz = thisJoinPoint.getTarget().getClass();
		String className = thisJoinPoint.getTarget().getClass().getSimpleName();
		String methodName = thisJoinPoint.getSignature().getName();
		System.out.println("AspectUsingAnnotaion.beforeTargetMethod executed");
		System.out.println(className + "." + methodName + "executed.");
	}
	
	/* 정상적으로 메소드가 실행될 때 수행 
	 * afterReturningTargetMethod() advice는 targetMethod()로 정의된 포인트컷 후에 수행.
	 * targetMethod() 포인트컷의 실행 결과는 retVal 변수에 저장되어  전달
	 */
	@AfterReturning(pointcut = "targetMethod()", returning = "retVal")
	public void afterReturningTargetMethod(JoinPoint thisJoinPoint, Object retVal){
		System.out.println("AspectUsingAnnotation.afterReturningTargetMethod executed." + " return value is [" + retVal + "]");
	}
	
	/* 메소드가 수행 중 예외사항을 반환하고 종료하는 경우 수행 
	 * afterThrowingTargetMethod() advice는 targerMethod()로 정의된 포인트컷에서 예외가 발생한 후에 수행.
	 * targetMethod() 포인트컷에서 발생된 예외는 exception 변수에 저장되어 전달
	 * */
	@AfterThrowing(pointcut = "targetMethod()", throwing = "exception")
	public void afterThrowingTargetMethod(JoinPoint thisJoinPoint, Exception exception) throws Exception{
		System.out.println("AspectUsingAnnotation.afterThrowingTargetMethod executed.");
		//System.out.println("에러가 발생했습니다.", exception);
		
		//throw new BizException("에러가 발생했습니다.", exception);
	}
	
	/* 메소드 수행 수 무조건 수행
	 * 정상 종료와 예외 발생 경우를 모두 처리해야 하는 경우에 사용
	 * 리소스 해제와 같은 작업이 해당
	 * */
    @After("targetMethod()")
    public void afterTargetMethod(JoinPoint thisJoinPoint) {
        System.out.println("AspectUsingAnnotation.afterTargetMethod executed.");
    }

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}

 

반응형

'programming > Spring & WEB' 카테고리의 다른 글

Spring) Spring MVC 동작 구조  (0) 2021.10.06
Spring) Maven, pom.xml 정의  (0) 2021.10.05
Spring) AOP 개념 및 설정 + 예제  (0) 2021.01.26

댓글