Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

여러 개의 Advisor 적용 본문

인프런/[인프런] 스프링 핵심 원리 - 고급

여러 개의 Advisor 적용

Seung__ 2022. 1. 1. 00:15

어드바이저는 하나의 포인트컷과 하나의 어드바이스를 가지고 있다.

만약 여러 어드바이저를 하나의 target 에 적용하려면 어떻게 해야할까?

쉽게 이야기해서 하나의 target 에 여러 어드바이스를 적용하려면 어떻게 해야할까?

프록시를 여러 개 만들면 될까?

 

 

 

1. 예제


public class MultiAdvisorTest {

    @Test
    @DisplayName("여러 프록시")
    void multiAdvisorTest(){
        //client -> proxy2(advisor2) -> proxy1(advisor1) -> target

        //프록시1 생성.
        ServiceInterface target = new ServiceImpl();
        ProxyFactory proxyFactory1 = new ProxyFactory(target);
        DefaultPointcutAdvisor advisor1 = new DefaultPointcutAdvisor(Pointcut.TRUE, new Advice1());
        proxyFactory1.addAdvisor(advisor1);
        ServiceInterface proxy1 = (ServiceInterface) proxyFactory1.getProxy();

        //프록시2 생성
        ProxyFactory proxyFactory2 = new ProxyFactory(proxy1);
        DefaultPointcutAdvisor advisor2 = new DefaultPointcutAdvisor(Pointcut.TRUE, new Advice2());
        proxyFactory2.addAdvisor(advisor2);
        ServiceInterface proxy2 = (ServiceInterface) proxyFactory2.getProxy();

        //실행
        proxy2.save();
    }

    @Slf4j
    static class Advice1 implements MethodInterceptor{

        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            log.info("Advice1 호출");
            return invocation.proceed();
        }
    }

    @Slf4j
    static class Advice2 implements MethodInterceptor{

        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            log.info("Advice2 호출");
            return invocation.proceed();
        }
    }
}

23:47:33.184 [main] INFO hello.proxy.advisor.MultiAdvisorTest$Advice2 - Advice2 호출
23:47:33.187 [main] INFO hello.proxy.advisor.MultiAdvisorTest$Advice1 - Advice1 호출
23:47:33.187 [main] INFO hello.proxy.common.service.ServiceImpl - save 호출
  • 포인트컷은 advisor1 , advisor2 모두 항상 true 를 반환하도록 설정했다. 
  • 따라서 둘다 어드바이스가 적용된다.
  • 여러 프록시의 문제
    • 이 방법이 잘못된 것은 아니지만, 프록시를 2번 생성해야 한다는 문제가 있다. 
    • 만약 적용해야 하는  어드바이저가 10개라면 10개의 프록시를 생성해야한다.

 

 

 

2. 하나의 프록시 여러 어드바이저


스프링은 이 문제를 해결하기 위해 하나의 프록시에 여러 어드바이저를 적용할 수 있게 만들어두었다.

@DisplayName("하나의 프록시, 여러 어드바이저")
void multiAdvisorTest2(){
    //client -> proxy2 -> advisor2 -> advisor1 -> target
    DefaultPointcutAdvisor advisor1 = new DefaultPointcutAdvisor(Pointcut.TRUE, new Advice1());
    DefaultPointcutAdvisor advisor2 = new DefaultPointcutAdvisor(Pointcut.TRUE, new Advice2());

    //프록시 생성.
    ServiceInterface target = new ServiceImpl();
    ProxyFactory proxyFactory = new ProxyFactory(target);

    //호출될 순서대로 넣음.
    proxyFactory.addAdvisor(advisor2);
    proxyFactory.addAdvisor(advisor1);
    ServiceInterface proxy = (ServiceInterface) proxyFactory.getProxy();

    proxy.save();
    
}

@Slf4j
static class Advice1 implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        log.info("Advice1 호출");
        return invocation.proceed();
    }
}

@Slf4j
static class Advice2 implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        log.info("Advice2 호출");
        return invocation.proceed();
    }
}
  • 프록시 팩토리에 원하는 만큼 addAdvisor() 를 통해서 어드바이저를 등록하면 된다.
  • 등록하는 순서대로 advisor 가 호출된다. 여기서는 advisor2 , advisor1 순서로 등록했다.

00:10:25.915 [main] INFO hello.proxy.advisor.MultiAdvisorTest$Advice2 - Advice2 호출
00:10:25.924 [main] INFO hello.proxy.advisor.MultiAdvisorTest$Advice1 - Advice1 호출
00:10:25.924 [main] INFO hello.proxy.common.service.ServiceImpl - save 호출

 

  • 실행 결과를 보면 advice2 , advice1 순서대로 호출된 것을 알 수 있다.
  • 결과적으로 여러 프록시를 사용할 때와 비교해서 결과는 같고, 성능은 더 좋다.

 

3. 중요


  • 스프링의 AOP를 처음 공부하거나 사용하면, AOP 적용 수 만큼 프록시가 생성된다고 착각하게 된다.
  • 스프링은 AOP를 적용할 때, 최적화를 진행해서 지금처럼 프록시는 하나만 만들고,
  • 하나의 프록시에 여러 어드바이저를 적용한다.
  • 정리하면 하나의 target 에 여러 AOP가 동시에 적용되어도,
  • 스프링의 AOP는 target 마다 하나의 프록시만 생성한다. 

 

4. GitHub : 220101 MultiAdvisor


 

GitHub - bsh6463/Spring_Advanced_2

Contribute to bsh6463/Spring_Advanced_2 development by creating an account on GitHub.

github.com

 

Comments