너무 많은 설정
@Bean
public OrderControllerV1 orderControllerV1(LogTrace logTrace) {
OrderControllerV1 orderController = new OrderControllerV1Impl(orderServiceV1(logTrace));
ProxyFactory factory = new ProxyFactory(orderController);
factory.addAdvisor(getAdvisor(logTrace));
OrderControllerV1 proxy = (OrderControllerV1) factory.getProxy();
log.info("ProxyFactory proxy={}, target={}", proxy.getClass(), orderController.getClass());
return proxy;
}
ProxyFactory를 통해 프록시를 빈으로 띄워야 하기 때문이다.컴포넌트 스캔

(@Bean, 컴포넌트 스캔 모두 포함)public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
}
BeanPostProcessor 인터페이스를 구현하고, 스프링 빈으로 등록하면 된다.postProcessBeforeInitialization: 객체 생성 이후에 @PostConstruct 같은 초기화 발생하기 전에 호출되는 프로세서postProcessAfterInitialization: 객체 생성 이후에 @PostConstruct 같은 초기화가 발생한 다음에 호출되는 프로세서@Bean
public AToBPostProcessor helloPostProcessor() {
return new AToBPostProcessor();
}
static class AToBPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof A) {
return new B();
}
return bean;
}
}
@PostConstruct의 비밀 스프링은
CommonAnnotationBeanPostProcessor라는 빈 후처리기를 자동으로 등록하는데, 여기에서@PostConstruct애노테이션이 붙은 메서드를 호출한다. 따라서 스프링 스스로도 스프링 내부의 기능을 확장하기 위해 빈 후처리기를 사용한다.
빈 후처리기로 프록시를 생성한다면 프록시를 생성하는 부분을 하나로 집중할 수 있다. 그리고 컴포넌트 스캔처럼 스프링이 직접 대상을 빈으로 등록하는 경우에도 중간에 빈 등록 과정을 가로채서 원본 대신에 프록시를 스프링빈으로 등록할 수 있다.
스프링은 프록시를 생성하기 위한 빈 후처리기를 이미 만들어서 제공한다.
build.gradle 추가
implementation 'org.springframework.boot:spring-boot-starter-aop'
라이브러리를 추가하면 aspectjweaver라는 aspectJ 관련 라이브러리를 등록하고, 스프링 부트가
AOP 관련 클래스를 자동으로 스프링 빈에 등록한다.
AnnotationAwareAspectJAutoProxyCreator라는 빈 후처리기가 스프링 빈에 자동으로 등록된다.Advisor들을 자동으로 찾아서 프록시가 필요한 곳에 자동으로 프록시를 적용해준다.Advisor 안에는 Pointcut과 Advice가 이미 모두 포함되어 있다. 따라서 Advisor만 알고 있으면 그 안에 있는 Pointcut으로 어떤 스프링 빈에 프록시를 적용해야 할지 알 수 있다. 그리고 Advice로 부가 기능을 적용하면 된다.참고
AnnotationAwareAspectJAutoProxyCreator는@AspectJ와 관련된 AOP 기능도 자동으로 찾아서 처리해준다. Advisor는 물론이고,@Aspect도 자동으로 인식해서 프록시를 만들고 AOP를 적용해준다.

@Bean , 컴포넌트 스캔 모두 포함)Advisor를 조회한다.Advisor에 포함되어 있는 포인트컷을 사용해서 해당 객체가 프록시를 적용할 대상인지 아닌지 판단한다. 이때 객체의 클래스 정보는 물론이고, 해당 객체의 모든 메서드를 포인트컷에 하나하나 모두 매칭해본다.AspectJ라는 AOP에 특화된 포인트컷 표현식을 적용할 수 있다. 지금은 특별한 표현식으로 복잡한 포인트컷을 만들 수 있구나 라고 대략 이해하면 된다.
@Bean
public Advisor advisor3(LogTrace logTrace) {
//pointcut
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* hello.proxy.app..*(..)) && !execution(* hello.proxy.app..noLog(..))");
//advice
LogTraceAdvice advice = new LogTraceAdvice(logTrace);
return new DefaultPointcutAdvisor(pointcut, advice);
}
AspectJExpressionPointcut : AspectJ 포인트컷 표현식을 적용할 수 있다.execution(* hello.proxy.app..*(..)) : AspectJ가 제공하는 포인트컷 표현식이다.
* : 모든 반환 타입hello.proxy.app.. : 해당 패키지와 그 하위 패키지*(..) : * 모든 메서드 이름, (..) 파라미터는 상관 없음&& : 두 조건을 모두 만족해야 함! : 반대hello.proxy.app 패키지와 하위 패키지의 모든 메서드는 포인트컷의 매칭하되, noLog() 메서드는 제외하라는 뜻이다.프록시 자동 생성기는 프록시를 하나만 생성한다. 왜냐하면 프록시 팩토리가 생성하는 프록시는 내부에 여러 advisor 들을 포함할 수 있기 때문이다.
자동 프록시 생성기인 AnnotationAwareAspectJAutoProxyCreator 덕분에 개발자는 매우 편리하게
프록시를 적용할 수 있다. 이제 Advisor만 스프링 빈으로 등록하면 된다.