Mastering Spring AOP: From @Aspect to ProxyFactoryBean and ProxyFactory

This guide explains how to define Spring AOP aspects with @Aspect, configure ProxyFactoryBean for fine‑grained proxy control, and create proxies programmatically using ProxyFactory, providing complete code examples and configuration details for Spring 6.1.2.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Spring AOP: From @Aspect to ProxyFactoryBean and ProxyFactory

In Spring 6.1.2, the @Aspect annotation is used to define aspects and create AOP proxies for modularizing cross‑cutting concerns.

1. Defining an Aspect with @Aspect

@Aspect
public class LogAspect {
    // Pointcut definition
    @Pointcut("execution(* com.pack..*.*(..))")
    public void log() {}

    // Before advice
    @Before("log()")
    public void beforeLog() {
        System.out.println("记录日志Before...");
    }

    // After advice
    @After("log()")
    public void afterLog() {
        System.out.println("记录日志After");
    }

    // After throwing advice
    @AfterThrowing(pointcut = "log()", throwing = "tx")
    public void ex(Throwable tx) {
        System.err.println("发生异常: " + tx.getMessage());
    }

    // Around advice
    @Around("log() && args(name)")
    public Object around(ProceedingJoinPoint pjp, String name) throws Throwable {
        System.out.println("log before...");
        System.out.println("name = " + name);
        Object ret = pjp.proceed();
        System.out.println("log after...");
        return ret;
    }
}

The aspect above demonstrates pointcut definition and four types of advice: before, after, after‑throwing, and around.

2. Creating Proxy Objects

2.1 ProxyFactoryBean

ProxyFactoryBean provides full control over pointcuts, advisors, and their order. It acts as a FactoryBean that returns the actual proxy from its getObject() method.

ProxyFactoryBean proxy = new ProxyFactoryBean();
// Whether to create a CGLIB proxy instead of an interface‑based proxy
proxy.setProxyTargetClass(false);
// Optimize CGLIB proxy (should be used only when fully understood)
proxy.setOptimize(false);
// Freeze configuration to prevent further changes
proxy.setFrozen(false);
// Expose the proxy in a ThreadLocal for target access
proxy.setExposeProxy(false);
// Interfaces to proxy (empty means use CGLIB on the target class)
proxy.setProxyInterfaces(new Class<?>[] {});
// Names of interceptors/advisors to apply
proxy.setInterceptorNames("interceptor01");
// Whether the bean should be a singleton
proxy.setSingleton(true);

Example usage with a DAO interface, a service class, and a configuration that registers a logging interceptor and the ProxyFactoryBean.

public interface CommonDAO {}

public class PersonService {
    public void save() {
        System.out.println("save method invoke...");
    }
}

@Configuration
public class AppConfig {
    @Bean
    public MethodInterceptor logInterceptor() {
        return new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("日志记录...");
                return invocation.proceed();
            }
        };
    }

    @Bean
    public ProxyFactoryBean personService() throws Exception {
        ProxyFactoryBean proxy = new ProxyFactoryBean();
        proxy.setProxyTargetClass(true);
        proxy.setTargetSource(new SingletonTargetSource(new PersonService()));
        proxy.setProxyInterfaces(new Class<?>[] {CommonDAO.class});
        proxy.setInterceptorNames("logInterceptor");
        return proxy;
    }
}

2.2 ProxyFactory

ProxyFactory allows programmatic creation of AOP proxies without relying on the Spring IoC container.

public interface CommonDAO {}

public class PersonService {
    public void save() {
        System.out.println("save method invoke...");
    }
}

public static void main(String[] args) {
    ProxyFactory factory = new ProxyFactory(new PersonService());
    factory.setProxyTargetClass(true);
    // Add a logging advice
    factory.addAdvice(new MethodInterceptor() {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("日志记录...");
            return invocation.proceed();
        }
    });
    // Add an advisor that matches the "save" method
    factory.addAdvisor(new PointcutAdvisor() {
        @Override
        public Advice getAdvice() {
            return new MethodInterceptor() {
                @Override
                public Object invoke(MethodInvocation invocation) throws Throwable {
                    System.out.println("权限控制...");
                    return invocation.proceed();
                }
            };
        }
        @Override
        public Pointcut getPointcut() {
            return new StaticMethodMatcherPointcut() {
                @Override
                public boolean matches(Method method, Class<?> targetClass) {
                    return method.getName().equals("save");
                }
            };
        }
    });
    PersonService ps = (PersonService) factory.getProxy();
    ps.save();
}

The article concludes with the complete code examples and encourages readers to apply these techniques in their projects.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaaopspringProxyFactoryBeanProxyFactory
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.