Gidhub BE Developer

Spring 프레임워크 핵심 기술 - 스프링 @AOP

2019-09-10
goodGid

이 글의 코드 및 정보들은 강의를 들으며 정리한 내용을 토대로 작성하였습니다.

  • 이전에 작성한 프록시 AOP글 이후에 작성된 글이다.

Spring AOP

  • 스프링 AOP를 사용하기위해선

  • 의존성을 추가해줘야한다.

  • 필자는 메이븐 빌드 툴을 사용하기 때문에

  • pom.xml에 의존성을 추가하였다.

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

Aspect 정의

@Component
@Aspect
public class PerfAspect {
    ...
}
  • @Aspect 어노테이션 선언을 통해

  • 해당 클래스는 Aspect로 사용됨을 명시해준다.

  • 그리고 스프링에서 제공해주는

  • 스프링 IoC를 사용하여

  • Component Scan 시 Bean 등록을 시키기 위해

  • @Component 어노테이션도 붙혀준다.


Advice 정의

public Object logPerf(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    long begin = System.currentTimeMillis();
    Object retVal = proceedingJoinPoint.proceed();
    System.out.println(System.currentTimeMillis() - begin);
    return retVal;
}

Advice 사용 방법

  • Advice는 3가지 방법으로 적용시킬 수 있다.

Before

  • @Before를 사용하면

  • 해당 어드바이스는 메소드가 실행되기 전에 동작한다.

After

  • @After를 사용하면

  • 해당 어드바이스는 메소드가 실행된 후 동작한다.

Around

  • Around는 Before + After 개념이다.

  • 즉 메소드가 실행되기 전과 후에 작업을 진행할 수 있다.


PointCut 정의

  • 위에서 정의한 Advice를

  • 어디에 적용시킬 것인가를 정의하자.

  • 2가지 방법이 있다.

Bean 이름을 통한 적용

@Around("bean(realEventService)")
public Object logPerf_Bean(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    System.out.println("Call logPerf_Bean()");
    long begin = System.currentTimeMillis();
    Object retVal = proceedingJoinPoint.proceed();
    System.out.println(System.currentTimeMillis() - begin);
    return retVal;
}

Annotation을 사용한 적용

  • 우선 Annotation를 정의한다.

Annotation

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface PerfLogging {
}
  • 그리고 Aspect의 Advice에

  • PointCut 방법으로

  • Annotation을 사용할 것임을 명시해준다.

@Around("@annotation(PerfLogging)")
public Object logPerf_Annotation (ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    System.out.println("Call logPerf_Annotation()");
    Object retVal = proceedingJoinPoint.proceed();
    return retVal;
}

Real Subject

  • Real Subject에서

  • AOP를 적용시킬 메소드에

  • 생성한 Annotation을 추가해준다.

@Service
public class RealEventService implements EventService {

    @PerfLogging
    @Override
    public void createEvent() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Creat Event");
    }

    ...

}

마무리

  • Advice를 적용키기 위한 3가지 방법과

  • PointCut을 명시하는 2가지 방법을 사용하여

  • Aspect를 정의하고

  • TC를 통해 각각 방법들의 결과를 확인해보자.

Spring AOP

@Component
@Aspect
public class PerfAspect {

    @Around("@annotation(PerfLogging)")
    public Object logPerf_Annotation (ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("Call logPerf_Annotation()");
        Object retVal = proceedingJoinPoint.proceed();
        return retVal;
    }

    @Around("bean(realEventService)")
    public Object logPerf_Bean(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("Call logPerf_Bean()");
        long begin = System.currentTimeMillis();
        Object retVal = proceedingJoinPoint.proceed();
        System.out.println(System.currentTimeMillis() - begin);
        return retVal;
    }

    @Before("bean(realEventService)")
    public void hello(){
        System.out.println("Call hello()");
    }

    @After("bean(realEventService)")
    public void goodBye(){
        System.out.println("Call goodBye()");
    }
}

Real Subject

@Service
public class RealEventService implements EventService {

    @PerfLogging
    @Override
    public void createEvent() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Creat Event");
    }

    @Override
    public void publishEvent() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Publish Event");
    }
}

Result

Call logPerf_Annotation()
Call logPerf_Bean()
Call hello()
Creat Event
1003
Call goodBye()

Call logPerf_Bean()
Call hello()
Publish Event
2002
Call goodBye()

참고


Similar Posts

Comments