ProxyFactoryBean vs @EnableAspectJAutoProxy. — Cracked Java
// Spring Framework & Spring Boot · AOP & Proxies
SeniorTheory

ProxyFactoryBean vs @EnableAspectJAutoProxy.

Both create AOP proxies, but they sit at opposite ends of the convenience spectrum. ProxyFactoryBean is the old, explicit, per-bean way: you manually wire one proxy, naming its target and interceptors. @EnableAspectJAutoProxy is the modern, declarative, automatic way: a post-processor scans every bean, matches it against all @Aspect pointcuts, and proxies whatever applies. In real Spring 6 / Boot apps you almost never write ProxyFactoryBean — but knowing it explains what the auto-proxy machinery does for you.

ProxyFactoryBean — manual, one bean at a time

A FactoryBean that produces a single proxy. You spell out the target and the advice chain:

@Bean
public ProxyFactoryBean orderService(OrderServiceImpl target,
                                      TxInterceptor txAdvice) {
    ProxyFactoryBean pfb = new ProxyFactoryBean();
    pfb.setTarget(target);
    pfb.setInterceptorNames("txAdvice");   // advice/advisor bean names
    pfb.setProxyTargetClass(true);         // force CGLIB
    return pfb;
}

Drawbacks that killed it for everyday use:

  • One declaration per proxied bean — doesn't scale past a handful.
  • You manage targets, interceptor names, and proxy type by hand.
  • Easy to get wrong (forget an interceptor, mis-name an advisor).

It still has niche uses: programmatically building a one-off proxy, or low-level control in framework code.

@EnableAspectJAutoProxy — declarative, automatic

Registers AnnotationAwareAspectJAutoProxyCreator, a BeanPostProcessor. As each bean is created, it:

  1. collects all @Aspect beans and their pointcuts,
  2. checks whether the bean matches any pointcut,
  3. if so, transparently wraps it in a proxy with the matching advice — without you declaring anything per bean.
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)   // Boot defaults this on
class AopConfig {}

You just write aspects:

@Aspect @Component
class TxAspect {
    @Around("@annotation(Transactional)")
    public Object around(ProceedingJoinPoint pjp) throws Throwable { ... }
}

…and every matching bean is proxied automatically.

Mark your status