做Spring开发时,@Transactional或@Async这些注解的动态代理是如何被创建的?Spring的ProxyFactory作为动态代理的核心工厂,封装了从配置到生成的全过程。本文将通过源码分析,揭示其内部工作机制与代理类型的决策逻辑。
一、ProxyFactory的核心定位:动态代理的“总指挥”
在Spring的AOP体系中,ProxyFactory是一个入口级的工具类。它封装了创建代理对象所需的所有流程,从配置Advisor、TargetSource,到最终生成代理实例,都由它统一调度和管理。
从类继承关系来看,ProxyFactory继承自ProxyCreatorSupport,而ProxyCreatorSupport实现了Advised接口(用于维护代理的配置信息,如拦截器链、目标类等)。因此,ProxyFactory的核心能力在于整合“配置管理”与“代理生成”两大功能,是理解Java动态代理底层实现的关键入口。
二、ProxyFactory创建代理的核心流程:从配置到实例
ProxyFactory生成代理的入口是getProxy()方法,其核心逻辑非常清晰:
// ProxyFactory.java
public Object getProxy() {
return createAopProxy().getProxy(); // 核心逻辑:创建AopProxy并生成代理
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate(); // 初始化:解析Advisor、TargetSource等配置
}
return getAopProxyFactory().createAopProxy(this); // 委托给AopProxyFactory
}
这两行代码构成了ProxyFactory的“心脏”:
createAopProxy():根据当前配置(如是否强制CGLIB、目标类是否为接口)创建具体的AopProxy实例(JDK动态代理或CGLIB代理的实现)。
getProxy():通过上一步创建的AopProxy实例生成最终的代理对象。
1. activate():初始化配置
activate()方法负责将配置的Advisor、TargetSource等信息“装配”成可执行的拦截器链。例如,当我们调用proxyFactory.addAdvice(new LoggingAdvice())时,activate()方法会将Advice包装成Advisor,并最终解析为拦截器链。
// ProxyCreatorSupport.java
protected void activate() {
this.active = true;
// 初始化AdvisorChainFactory:用于生成拦截器链
if (this.advisorChainFactory == null) {
this.advisorChainFactory = new DefaultAdvisorChainFactory();
}
}
三、DefaultAopProxyFactory:代理类型的“决策者”
ProxyFactory将代理类型的选择委托给DefaultAopProxyFactory。它的核心方法createAopProxy(AdvisedSupport config)决定了使用JDK动态代理还是CGLIB代理。
// DefaultAopProxyFactory.java
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 判断是否需要CGLIB代理的三大条件
if (config.isOptimize() // 1. 是否优化(优先CGLIB)
|| config.isProxyTargetClass() // 2. 是否强制代理目标类
|| hasNoUserSuppliedProxyInterfaces(config)) { // 3. 目标类是否没有实现接口
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class");
}
// 特殊情况:如果目标类本身就是接口或是代理类,仍使用JDK代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 默认情况下,使用CGLIB代理
return new ObjenesisCglibAopProxy(config);
} else {
// 否则,使用JDK动态代理
return new JdkDynamicAopProxy(config);
}
}
这段代码清晰地回答了Spring何时使用JDK代理,何时使用CGLIB这一问题:
- 优先使用JDK动态代理(基于接口)。
- 当满足以下任一条件时,则使用CGLIB代理:
- 配置了
proxyTargetClass = true(强制代理目标类本身)。
- 目标类没有实现任何接口。
- 配置了
optimize = true(优先性能优化,历史上更倾向CGLIB)。
四、JDK vs CGLIB:两种代理的底层实现差异
了解决策逻辑后,我们进一步深入两种代理的底层生成机制。
1. JDK动态代理:基于接口的代理
JDK动态代理的实现类是JdkDynamicAopProxy,其核心方法是getProxy():
// JdkDynamicAopProxy.java
public Object getProxy(ClassLoader classLoader) {
// 1. 补全代理接口(例如Advised接口,用于查询代理配置)
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
// 2. 处理equals和hashCode方法
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 3. 调用JDK原生API生成代理实例
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
Proxy.newProxyInstance()是JDK提供的标准API,其第三个参数InvocationHandler是关键。JdkDynamicAopProxy自身就实现了InvocationHandler接口,因此当代理对象的方法被调用时,会触发其invoke()方法:
// JdkDynamicAopProxy.java (invoke方法核心逻辑)
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
...
// 1. 获取拦截器链(例如@Transactional对应的事务拦截器)
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 2. 无拦截器:直接反射调用目标方法
if (chain.isEmpty()) {
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
} else {
// 3. 有拦截器:执行拦截器链(事务的开启→执行目标方法→提交/回滚)
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed(); // 链式调用
}
...
}
invoke()方法的核心在于拦截器链的执行。ReflectiveMethodInvocation.proceed()会依次执行链中的每个拦截器,最终调用目标方法,这就是Spring AOP机制中“环绕通知”的底层实现。
2. CGLIB动态代理:基于继承的代理
CGLIB代理的实现类是ObjenesisCglibAopProxy(Spring 4+引入,用于解决CGLIB无法代理无默认构造函数类的问题)。其核心是利用CGLIB的Enhancer类生成代理子类。
// ObjenesisCglibAopProxy.java
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false); // 构造方法不拦截
// 根据是否有构造参数选择创建方式
return (this.constructorArgs != null && this.constructorArgTypes != null) ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) : // 带参构造
enhancer.create(); // 无参构造
}
CGLIB通过继承目标类来生成代理类(这是它能代理非接口方法的原因)。生成的代理类会重写所有非final方法,并将调用转发给MethodInterceptor。Spring的CglibAopProxy实现了该接口,其intercept()方法的执行逻辑与JDK代理的invoke()类似。
五、ProxyFactory的“隐藏技能”:自定义代理逻辑
除了默认的JDK/CGLIB代理,ProxyFactory支持自定义AopProxy。你可以通过实现AopProxyFactory接口,完全控制代理的生成逻辑,这体现了Spring框架强大的扩展性。
// 自定义AopProxyFactory示例
public class CustomAopProxyFactory implements AopProxyFactory {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 自定义逻辑:例如,始终返回CGLIB代理
return new ObjenesisCglibAopProxy(config);
}
}
// 使用自定义Factory
ProxyFactory proxyFactory = new ProxyFactory(target);
proxyFactory.setAopProxyFactory(new CustomAopProxyFactory());
Object proxy = proxyFactory.getProxy();
六、ProxyFactory的“避坑指南”
- 不要代理final类/方法:CGLIB通过继承生成代理,final类无法被继承,final方法无法被重写。
- 注意TargetSource的生命周期:如果TargetSource被配置为
Prototype(多例),ProxyFactory每次调用都会创建新的目标对象,需注意资源及时释放。
- 正确使用
exposeProxy属性:如果需要在目标方法内部获取当前的代理对象(例如通过AopContext.getCurrentProxy()调用自身另一个被AOP管理的方法),必须设置proxyFactory.setExposeProxy(true)。这涉及到代理模式在复杂场景下的应用。
结尾
通过源码分析可以看出,ProxyFactory的核心逻辑并不复杂,遵循着“配置→决策→生成”的清晰流程。理解它,不仅能让你深入掌握Spring AOP的底层原理,也为你设计和实现自己的代理机制提供了清晰的思路。