본문 바로가기

학원/복기

[Spring] AOP 어노테이션

AopAnnotationBean

//AopAnnotationBean 클래스를 스프링빈으로 등록
@Component
public class AopAnnotationBean {
	public void display1() {
		System.out.println("*** AopAnnotationBean 클래스의 display1() 메소드 실행 ***");
	}
	
	public void display2() {
		System.out.println("*** AopAnnotationBean 클래스의 display2() 메소드 실행 ***");
	}
	
	public void display3() {
		System.out.println("*** AopAnnotationBean 클래스의 displa3() 메소드 실행 ***");
	}
}

 

AopAnnotationApp

public class AopAnnotationApp {
	public static void main(String[] args) {
		ApplicationContext context=new ClassPathXmlApplicationContext("07-5_aopAnnotation.xml");
		AopAnnotationBean bean=context.getBean("aopAnnotationBean", AopAnnotationBean.class);
		System.out.println("==========================================================");
		bean.display1();
		System.out.println("==========================================================");
		bean.display2();
		System.out.println("==========================================================");
		bean.display3();
		System.out.println("==========================================================");
		((ClassPathXmlApplicationContext)context).close();
	}
}

 

 

네임스페이스에 aop, beans, context 3가지를 등록해서  xml 파일 선언 

 

 

07-5_aopAnnotation.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"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
	
        <!--xyz.itwill07.aop 패키지와 하위 패키지를 스캔하여 스프링 빈으로 등록-->
	<context:component-scan base-package="xyz.itwill07.aop"/>
    
	<aop:aspectj-autoproxy/>
</beans>

 

 

<aop:aspectj-autoproxy>는 AspectJ AOP를 사용하여 자동 프록시를 생성하도록 지정하는 역할을 한다.

 

AspectJ는 스프링 프레임워크의 AOP 기능을 보다 강력하게 확장한 라이브러리로, 특정 클래스나 메서드의 호출에 대해 사전 및 사후에 횡단 관심사를 적용할 수 있도록 해준다.

AspectJ는 @Aspect 어노테이션을 이용해 AOP 기능을 구현하고, AspectJ 프록시를 사용하여 스프링 빈들을 감싸서 AOP를 적용한다.

 

 

* 어노테이션 정리

 

@Aspect : 핵심관심코드에 횡단관심코드를 삽입하여 실행하기 위한 기능을 제공하는 어노테이션
→ Spring Bean Configuration File의 aspect 엘리먼트와 유사한 기능을 제공하는 어노테이션이다.

  
@Pointcut : 타겟메소드를 지정하기 위한 어노테이션

→ 메소드를 호출하여 Pointcut 표현식으로 설정된 타겟메소드를 제공받아 사용한다.

→ Spring Bean Configuration File의 pointcut 엘리먼트와 유사한 기능을 제공한다.

  • value 속성 : 타겟메소드를 지정하기 위한 Pointcut 표현식을 속성값으로 설정한다. 
  • → 다른 속성값이 없는 경우 속성값만 설정하는 것이 가능하다. 

@Before : 타겟메소드의 핵심관심코드 실행 전 삽입되어 실행될  횡단관심코드를 제공하기 위한 어노테이션 

→ Spring Bean Configuration File의 before 엘리먼트와 유사한 기능을 제공한다.

  • value 속성 : 타겟메소드를 지정하기 위한 Pointcut 표현식을 속성값으로 설정한다.
  • → 다른 속성값이 없는 경우 속성값만 설정하는 것이 가능하다.
  • → @Pointcut 어노테이션을 사용한 메소드를 호출하여 Pointcut 표현식을 제공받아 사용하는 것도 가능하다.

@After : 타겟메소드의 핵심관심코드 실행 후 반드시 삽입되어 실행될  횡단관심코드를 제공하기 위한 어노테이션

→ Spring Bean Configuration File의 after 엘리먼트와 유사한 기능을 제공한다.

 

@AfterReturning : 타겟메소드의 핵심관심코드가 정상적으로 실행된 후 삽입되어 실행될  횡단관심코드를 제공하기 위한 어노테이션

→ Spring Bean Configuration File의 after-returning 엘리먼트와 유사한 기능을 제공한다.

  • returning 속성 : 타겟메소드의 반환값을 전달받아 저장하기 위한 매개변수의 이름을 속성값으로 설정한다.

@AfterThrowing : 타겟메소드의 핵심관심코드 실행시 예외가 발생된 삽입되어 실행될 횡단관심코드를 제공하기 위한 어노테이션 

→ Spring Bean Configuration File after-throwing 엘리먼트와 유사한 기능 제공

  • throwing 속성 : 타겟메소드에서 발생된 예외를 전달받아 저장하기 위한 매개변수의 이름을 속성값으로 설정한다.

@Around : 타겟메소드의 핵심관심코드 실행 전과 후에 삽입되어 실행될 횡단관심코드를 제공하기 위한 어노테이션 

 

 

 

AopAnnotationAdvice

@Slf4j
@Component
@Aspect //핵심관심코드에 횡단관심코드를 삽입하여 실행하기 위한 기능을 제공
public class AopAnnotationAdvice {
	//타겟 메서드 지정
	@Pointcut("within(xyz.itwill07.aop.AopAnnotationBean)")//AopAnnotationBean 클래스에 정의된 모든 메서드를 타겟 메서드로 선택
	public void aopPointCut() {}
	
	//타겟메소드의 핵심관심코드 실행 전 삽입되어 실행될 횡단관심코드를 제공
	//@Before("within(xyz.itwill07.aop.AopAnnotationBean)")
	@Before("aopPointCut()") //Pointcut 표현식을 제공 받아 사용 가능
	public void beforeLog() {
		log.info("[before]핵심관심코드 실행 전에 삽입되어 실행될 횡단관심코드");
	}

	//타겟메소드의 핵심관심코드 실행 후 반드시 삽입되어 실행될 횡단관심코드를 제공
	@After("aopPointCut()")
	public void afterLog() {
		log.info("[after]핵심관심코드 실행 후에 반드시 삽입되어 실행될 횡단관심코드");
	}

	//타겟메소드의 핵심관심코드가 정상적으로 실행된 후 삽입되어 실행될 횡단관심코드를 제공
	//returning 속성 : 타겟메소드의 반환값을 전달받아 저장하기 위한 매개변수의 이름을 속성값으로 설정 
	@AfterReturning(value="aopPointCut()", returning = "object")
	public void afterReturningLog(Object object) {
		log.info("[after-returning]핵심관심코드가 정상적으로 실행 후에 삽입되어 실행될 횡단관심코드");
	}

	//타겟메소드의 핵심관심코드 실행시 예외가 발생된 후 삽입되어 실행될 횡단관심코드를 제공
	//throwing 속성 : 타겟메소드에서 발생된 예외를 전달받아 저장하기 위한 매개변수의 이름을 속성값으로 설정 
	@AfterThrowing(value="aopPointCut()", throwing = "exception")
	public void afterThrowingLog(Exception exception) {
		log.info("[after-throwing]핵심관심코드 실행시 예외가 발생된 후에 삽입되어 실행될 횡단관심코드");
	}

	//타겟메소드의 핵심관심코드 실행 전과 후에 삽입되어 실행될 횡단관심코드를 제공
	@Around("aopPointCut()")
	public Object aroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
		log.info("[around]핵심관심코드 실행 전에 삽입되어 실행될 횡단관심코드");
		Object result=joinPoint.proceed();
		log.info("[around]핵심관심코드 실행 후에 삽입되어 실행될 횡단관심코드");
		return result;
	}
}