이전글 : 스프링 AOP 기본 동작 원리 : https://chalchichi.tistory.com/41
1. 스프링 AOP 메이븐 의존성을 추가한다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2. 어노테이션 기반으로 실행예정이므로 어노테이션을 만들어준다.
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface AOPLOG {
}
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface AOPLOG2 {
}
- @AOPLOG1, @AOPLOG2
- 메서드에 대한 프록시이므로 Target은 메서드
- Retention을 Source로 설정할 경우 해당 어노테이션은 주석으로써의 기능 밖에 가지지 못하므로 동적 프록시를 생성해야되는 메서드를 구별하지 못하여 AOP가 동작하지 못한다.
3. 프록시가 동작해야할 main Subject 를 생성한다.
package com.example.aopexample;
import org.springframework.stereotype.Component;
@Component
public class SomethingtoDo {
@AOPLOG
public void Do()
{
int a = 0;
for(int i=0 ;i<1000;i++) {
a += i;
}
System.out.println("Do-1 End");
}
@AOPLOG2
public Integer Do2(int parameter1, int parameter2)
{
int a = 0;
for(int i=0 ;i<parameter1;i++) {
a += i;
}
System.out.println("Do-2 End");
return a;
}
}
- SomethingtoDo 객체 생성
- 빈으로 등록되어야 스프링 AOP적용이 가능하다.
- 파라미터가 없고 void 리턴인 Do1 메서드에는 @AOPLOG1 , 둘다 가지고 있는 Do2 메서드에는 @AOPLOG2를 붙여준다.
4. Aspect를 정의한다.
package com.example.aopexample;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class SpringAspect {
//포인트컷을 해당 어노테이션으로 적용
//구동시간 출력
@Around("@annotation(AOPLOG)")
public Object logperf(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
//리턴값이 없지만 object로 받아와서 메서드를 끝내야 한다.
Object res = pjp.proceed();
System.out.println("Time : " + (System.currentTimeMillis()-start)/1000);
return res;
}
//파라미터와 리턴값 출력
@Around("@annotation(AOPLOG2)")
public Object logperf2(ProceedingJoinPoint pjp) throws Throwable {
//파라미터와 리턴값을 object로 받아서 캐스팅후 사용할 수 있다.
Object res = pjp.proceed();
Object[] paras = pjp.getArgs();
for(int i=0; i< paras.length; i++)
{
System.out.println("Parameter"+i+" :" + (Integer)paras[i]);
}
System.out.println("Return : " + (Integer)res);
return res;
}
}
- @Aspect 어노테이션을 붙여준다.
- 빈으로 등록하여야 한다.
- Around, Before등으로 어드바이스를 정의 할수 있다.
- 어드바이드 내부 옵션으로 포인트컷을 정의한다. (@annotation("어노테이션 이름") , bean(빈 이름) , excution(클래스 경로))
- return type 이 Object , 파라미터가 ProceedingJoinPoint 인 메서드를 정의하고 Aspect로 등록한다.
- ProceedingJoinPoint의 proceed 메서드 를 통해 main subject를 진행하고 리턴값을 받을 수 있다 . (Object type)
- ProceedingJoinPoint의 get 메서드 를 통해 main subject를 진행하고 파라미터를 배열로 받을 수 있다. (Object type)
5. 어플리케이션 구동 및 결과
package com.example.aopexample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class Run implements ApplicationRunner {
@Autowired
SomethingtoDo somethingtoDo;
@Override
public void run(ApplicationArguments args) throws Exception {
somethingtoDo.Do();
somethingtoDo.Do2(1000 , 2000);
}
}
- 해당 메서드가 실행 된 후에 프록시가 동작함을 확인 할 수 있다.
- 결과
Do-1 End
Time : 0
Do-2 End
Parameter0 :1000
Parameter1 :2000
Return499500
'Tools > Spring' 카테고리의 다른 글
스프링 AOP 기본 동작 원리 (0) | 2021.02.27 |
---|---|
Component와 Component Scan (0) | 2020.08.09 |
ApplicationContext-2 (Autowired) (0) | 2020.08.06 |
ApplicationContext-1 (Bean을 등록하는 방법) (0) | 2020.08.04 |
Spring Ioc 컨테이너와 Bean (0) | 2020.08.04 |