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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
