Tools/Spring

스프링 AOP 적용 예제

칼쵸쵸 2021. 2. 28. 00:08

이전글 : 스프링 AOP 기본 동작 원리 : https://chalchichi.tistory.com/41

 

스프링 AOP 기본 동작 원리

스프링 AOP - OOP를 보완하기 위해 ASPECT를 모듈화 할 수 있는 프로그래밍 기법 구성요소 1. Aspect : 묶어 놓은 모듈 2. Target : 적용이 되는 대상 3. Advice : Aspect 안의 기능 4. Join Point : 적용 시점 5...

chalchichi.tistory.com

 

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