본문 바로가기

개발/Spring

AOP - @AOP

반응형

스프링 애노테이션 기반의 스프링 @AOP

1. 의존성 추가 

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. 애스팩트 정의 

package com.bpkim.demospring51;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class PerfAspect {

    // ProceedingJoinPoint > 어드바이스가 적용될 대상
    // 어드바이스 : 할일, aspect

    // 타겟에 해당하는 메소드를 호출하고 결과값 리턴
    // @Around("") >> 안에 포인트 컷을 적용 시킬 수 있다.
    //              >> 메소드 호출을 감싸고 있기때문에 호출 전 호출후 할일을 정할 수 있다. 에러 발생시 할일도 적영할 수 있다.
    // @Around("execution(* com.bpkim..*.EventService.*(..))")
    // >> 이벤트 클래스 안에 있는 모든 메소드에 이 일을 한다.

    @Around("execution(* com.bpkim..*.EventService.*(..))")
    public Object logPerfAllEventServiceMethod(ProceedingJoinPoint pjp) throws Throwable{
        long begin = System.currentTimeMillis();
        Object retVal = pjp.proceed(); // 메소드 호출
        System.out.println(System.currentTimeMillis() - begin);
        return retVal;
    }
    /*>>> 이렇게 하면 모든 함수에 적용
    >>> deleteEvent 메소드에는 적용 안하고 싶다 >> 애노테이션을 만들어 선언하자
    */

    // PerLoggin 애노테이션 쓰는 곳에서만 적용
    @Around("@annotation(PerLogging)")
    public Object logPerfAnnotation(ProceedingJoinPoint pjp) throws Throwable{
        long begin = System.currentTimeMillis();
        Object retVal = pjp.proceed(); // 메소드 호출
        System.out.println(System.currentTimeMillis() - begin);
        return retVal;
    }

    // 빈으로 적용
    // 빈이 가지고 있는 모든 메소드에 적용
    @Around("bean(simpleEventService)")
    public Object logPerfBean(ProceedingJoinPoint pjp) throws Throwable{
        long begin = System.currentTimeMillis();
        Object retVal = pjp.proceed(); // 메소드 호출
        System.out.println(System.currentTimeMillis() - begin);
        return retVal;
    }


    @Before("bean(simpleEventService)")
    public void logPerfBeforeBean() throws Throwable{
        System.out.println("hello ");
    }
}

- @Around
  메소드 호출을 감싸고 있는 aspect 구현가능  
  메소드를 감싸고 있기 때문에 호출 전, 호출 후, 호출 중 에러 발생 등 에 할일을 작성할 수 있다.

- @Around 사용 
   1) @Around("execution(* com.bpkim..*.EventService.*(..))")
      com.bpkim 으로시작하고 EventService으로 끝나는클래스의 모든 메소드에 적용 
   2) @Around("@annotation(PerLogging)")
      PerLogging 애노테이션을 쓰는 메소드에만 적용
  PerLogging애노테이션 사용 

package com.bpkim.demospring51;

import java.lang.annotation.*;

// @Retention(RetentionPolicy.CLASS)
// 애노테이션 정보를 얼마나 유지할것인가
//  RetentionPolicy.CLASS > 컴파일하고 클래스에도 남길 것
//  RetentionPolicy.SOURCE> 소스에만 있음
//  기본 값으로 해도 된다.
@Documented
@Target(ElementType.METHOD) // 메소드에 적용
@Retention(RetentionPolicy.CLASS)
public @interface PerLogging {
}

- PerLogging 애노테이션 적용

package com.bpkim.demospring51;

import org.springframework.stereotype.Service;

/* */
@Service
public class SimpleEventService implements EventService {

    @PerLogging
    @Override
    public void createEvent() {

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Created an event");
    }

    @PerLogging
    @Override
    public void publishEvent() {

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Published an event");
    }

    public void deleteEvent(){
        System.out.println("Delete an event");
    }
}

>> @PerLogging 을 적용한 createEvent(), publishEvent()에만 AOP적용

3) @Around("bean(simpleEventService)")
   빈 이름으로 적용
  simpleEventService을 이름을 가진 빈에 모든 메소드에 적용
4) @Before("bean(simpleEventService)")
  simpleEventService을 이름을 가진 빈에 모든 메소드의 실행전 적용   

반응형

'개발 > Spring' 카테고리의 다른 글

Null-Safety  (0) 2021.04.27
AOP - 프록시 기반 AOP  (0) 2021.04.27
스프링 AOP - 개념  (0) 2021.04.27
SpEL(스프링 Expression Language)  (0) 2021.04.23
데이터 바인딩 추상화 Converter와 Formatter  (0) 2021.04.23