https://megamaker.tistory.com/353
[Spring] 빈 후처리기 (BeanPostProcessor)
https://megamaker.tistory.com/352 [Spring] Advisor 이용해서 Proxy Factory 사용하기https://megamaker.tistory.com/351 [Spring] 프록시 팩토리(Proxy Factory) 사용하기https://megamaker.tistory.com/349 [Java] 동적 프록시 (Dynamic Proxy)
megamaker.tistory.com
ㄴ 지난 게시글
지난번에는 빈 후처리기를 사용해서 Advisor를 등록하고 사용해봤는데 스프링에서 자동으로 만들어주는 빈 후처리기가 있는데 이게 바로 AnnotationAwareAspectJAutoProxyCreator이다. 이번에는 이 자동 프록시 생성기를 이용해서 이전의 로직을 구현해보겠다.
자동 프록시 생성기 사용하기
implementation 'org.springframework.boot:spring-boot-starter-aop'
자동 프록시 생성기를 사용하려면 위 라이브러리를 추가해야 한다.
public interface MyTextInterface {
void print(String text);
}
@Slf4j
public class MyTextImpl implements MyTextInterface {
@Override
public void print(String text) {
log.info(text);
}
}
위 인터페이스와 구현체는 비즈니스 로직 관련 코드이다.
@Slf4j
public class MyTextAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
log.info("=================");
Object result = invocation.proceed();
log.info("=================");
return result;
}
}
부가 기능 로직이 있는 Advice 코드이다.
@SpringBootTest
public class AutoProxyTest {
@Autowired
MyTextInterface myText;
@Test
void test() {
myText.print("자동 프록시 생성기 테스트");
}
@TestConfiguration
static class AutoProxyConfig {
@Bean
public MyTextInterface myText() {
return new MyTextImpl();
}
@Bean
public Advisor advisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* hello.proxy.myProxy.dynamic..*(..))");
MyTextAdvice advice = new MyTextAdvice();
return new DefaultPointcutAdvisor(pointcut, advice);
}
}
}

자동 프록시 생성기는 말 그대로 자동으로 생성해주기 때문에 따로 프록시를 만들기 위한 코드를 작성할 필요는 없고, Pointcut과 Advice를 포함하고 있는 Advisor를 스프링 빈으로 등록하기만 하면 된다. 이렇게 하면 포인트컷으로 설정한 조건에 맞는 스프링 빈을 찾아서 프록시로 변경하고 해당 인스턴스를 원래 스프링 빈 이름으로 프록시를 등록한다.
위 테스트에서 MyTextImpl()을 생성하고 스프링 빈으로 등록했지만 어느 곳에서도 해당 인스턴스를 프록시로 바꾸는 코드는 없다. 자동 프록시 생성기에서 알아서 해주기 때문에 그냥 원래 빈을 주입받는 것처럼 사용하면 자동으로 프록시 인스턴스를 주입받게 된다.
@Test
void test() {
myText.print("자동 프록시 생성기 테스트");
log.info("myText.getClass() = {}", myText.getClass());
}

주입받은 빈의 타입을 조회해보면 CGLIB으로 생성된 프록시인 것을 알 수 있다. 스프링에서는 따로 설정하지 않으면 CGLIB로 프록시를 설정한다고 한다.
@Aspect 사용하기
다음 게시글에서 자세히 알아보겠지만 미리 @Aspect를 사용해보았다. 자동 프록시 생성기 AnnotationAwareAspectJAutoProxyCreator는 자동으로 Advisor를 찾아서 등록하지만 다른 기능도 있다.
@Aspect 어노테이션이 붙은 클래스를 Advisor로 변환하여 등록해준다.
처음 실행하는 시점에 Advisor인 빈을 찾아서 등록하고, Aspect 어드바이저 빌더를 통해 @Aspect가 붙은 클래스도 찾아서 @Around가 붙은 각 메서드를 Advisor로 등록한다. @Around, @Before와 같은 어노테이션 내에는 AspectJ의 문법을 사용하지만 실제로 AspectJ가 처리하는 것은 아니고 스프링 AOP에서 AspectJ의 문법만 사용하는 것이라고 한다.
프록시를 적용하는 방법은 컴파일 시점, 클래스 로드 시점, 런타임 시점이 있는데 지금까지 했던 프록시 생성 방식은 런타임 시점이었다. 컴파일 시점과 클래스 로드 시점은 AspectJ로 적용 할 수 있지만 배울 내용도 많고 어렵기 때문에 기능은 적지만 부족한 것은 없는 스프링 AOP만 사용해도 충분하다고 한다.
@Slf4j
@Import(AutoProxyTest.AspectTest.class)
@SpringBootTest
public class AutoProxyTest {
@Autowired
MyTextInterface myText;
@Test
void test() {
myText.print("자동 프록시 생성기 테스트");
log.info("myText.getClass() = {}", myText.getClass());
}
@TestConfiguration
static class AutoProxyConfig {
@Bean
public MyTextInterface myText() {
return new MyTextImpl();
}
}
@Slf4j
@Aspect
static class AspectTest {
@Around("execution(* hello.proxy.myProxy.dynamic..*(..))")
public Object logic(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("=================");
Object result = joinPoint.proceed();
log.info("=================");
return result;
}
}
}

앞의 코드에서 직접 Advisor를 생성하는 부분을 빼고 @Aspect로 Advisor를 생성하도록 변경했다. @Around에 Pointcut을 작성한다. @Around 말고도 @Before나 여러 가지 있지만 target의 로직을 감싸야 하기 때문에 Around를 사용했다. 각 어노테이션마다 target의 앞에서만 실행되거나 뒤에서만 실행되거나 등 여러 시점에 호출되기 때문에 상황에 맞는 어노테이션을 사용해야 한다.
결과
지금까지 여러 가지를 직접 생성하고 등록해서 프록시를 사용했는데 이제는 Pointcut, Advice, Advisor, proxy factory까지 자동으로 생성해주고 등록해주는 기능을 사용하니 코드도 간결해지고 사용하기도 편해졌다. 다음에는 포인트컷 지시자에 대해서 학습할텐데 배울 내용이 많아서 복습을 많이 해야할 것 같다.
'공부 > Spring' 카테고리의 다른 글
| [Servlet] 서블릿 컨테이너 초기화 (0) | 2024.08.04 |
|---|---|
| [Spring] 포인트컷 지시자(Pointcut Designator) (0) | 2024.07.31 |
| [Spring] 빈 후처리기 (BeanPostProcessor) (0) | 2024.07.27 |
| [Spring] Advisor 이용해서 Proxy Factory 사용하기 (0) | 2024.07.26 |
| [Spring] 프록시 팩토리(Proxy Factory) 사용하기 (0) | 2024.07.25 |