0%

ProxyFactoryBean

Spring ProxyFactoryBean 深度解析:AOP 代理的底层实现核心

ProxyFactoryBean 是 Spring AOP 与 IOC 容器融合的关键组件,它实现了 FactoryBean 接口,专门用于在 IOC 环境中创建 AOP 代理对象。不同于 @AspectJ 等高层注解驱动的 AOP 方式,ProxyFactoryBean 是更底层的实现,直接暴露了 AOP 代理的配置细节(如通知器链、代理类型选择)。从 “核心定位→源码流程→代理生成逻辑→JDK/CGLIB 对比” 四个维度,彻底讲透 ProxyFactoryBean 如何完成 AOP 代理的创建。

ProxyFactoryBean 的核心定位

在 Spring AOP 体系中,ProxyFactoryBean 的角色是 “IOC 容器中的 AOP 代理工厂”,其核心职责是:

  1. 整合 AOP 配置:管理通知(Advice)、切入点(Pointcut)、目标对象(Target)等 AOP 核心元素;
  2. 构建通知器链:将配置的拦截器 / 通知组装成 Advisor 链(AOP 拦截逻辑的执行顺序由链决定);
  3. 生成代理对象:根据目标对象类型(接口 / 类)自动选择 JDK 动态代理或 CGLIB 代理,最终通过 getObject() 方法向容器暴露代理对象。

关键继承与实现关系

ProxyFactoryBean 继承了 AdvisedSupport(封装 AOP 配置的核心类),实现了 FactoryBean<Object>(IOC 容器的工厂 Bean 接口),其类结构如下:

1
2
3
ProxyFactoryBean 
├─ 继承:AdvisedSupport(管理 Advisor、TargetSource、代理配置)
└─ 实现:FactoryBean<Object>(通过 getObject() 生成代理对象)
  • AdvisedSupport:存储 AOP 代理的所有配置(目标对象、通知器链、代理类型等),是 AOP 代理生成的 “数据源”;
  • FactoryBean:让 ProxyFactoryBean 成为 IOC 中的 “工厂 Bean”—— 容器获取的不是 ProxyFactoryBean 本身,而是其 getObject() 方法返回的AOP 代理对象

ProxyFactoryBean 核心流程:从配置到代理生成

Aop生成过程

ProxyFactoryBean 的核心入口是 getObject() 方法(实现自 FactoryBean),整个流程可分为 “初始化通知器链→生成代理实例→选择代理类型→创建具体代理” 四步。

入口方法:getObject()—— 触发代理创建

getObject() 是 ProxyFactoryBean 的核心方法,负责判断代理的作用域(单例 / 原型),并调用对应的逻辑生成代理对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
public Object getObject() throws BeansException {
// 步骤1:初始化通知器链(将配置的拦截器转为 Advisor 链)
initializeAdvisorChain();

// 步骤2:根据作用域生成代理(单例/原型)
if (isSingleton()) {
// 单例代理:创建后缓存,后续 getBean() 直接复用
return getSingletonInstance();
} else {
// 原型代理:每次 getBean() 都创建新代理
return newPrototypeInstance();
}
}
  • 单例代理:默认模式,代理对象创建后缓存到 singletonInstance 字段,容器生命周期内仅创建一次;
  • 原型代理:每次获取 Bean 时都重新创建代理,适用于目标对象为原型的场景。

步骤 1:initializeAdvisorChain()—— 构建 AOP 通知器链

AOP 代理的核心是 “拦截逻辑的执行”,而通知器链(Advisor Chain)是拦截逻辑的组织形式(每个 Advisor 包含 “切入点 + 通知”)。initializeAdvisorChain() 的作用是将配置的 interceptorNames(拦截器 Bean 名称列表)转为实际的 Advisor 链。

源码逻辑拆解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) { // 避免重复初始化
return;
}

if (!ObjectUtils.isEmpty(this.interceptorNames)) { // 若配置了拦截器名称列表
if (this.beanFactory == null) { // 依赖 IOC 容器获取拦截器Bean
throw new IllegalStateException("无 BeanFactory,无法解析拦截器名称");
}

// 遍历所有拦截器名称,构建 Advisor 链
for (String name : this.interceptorNames) {
// 1. 处理全局通知(名称以 "*" 结尾,如 "globalAdvisor*")
if (name.endsWith(GLOBAL_SUFFIX)) {
// 从容器中获取所有类型匹配的全局 Advisor
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
// 2. 处理普通拦截器/通知(指定具体 Bean 名称)
else {
Object advice;
// 单例拦截器:直接从容器获取实例
if (this.singleton || this.beanFactory.isSingleton(name)) {
advice = this.beanFactory.getBean(name);
}
// 原型拦截器:用占位符暂存,避免提前创建实例
else {
advice = new PrototypePlaceholderAdvisor(name);
}
// 将拦截器转为 Advisor 并加入链
addAdvisorOnChainCreation(advice, name);
}
}
}

this.advisorChainInitialized = true; // 标记初始化完成
}
关键逻辑说明
  • interceptorNames:ProxyFactoryBean 的核心配置属性,存储拦截器 / 通知的 Bean 名称(如 ["logInterceptor", "transactionInterceptor"]),配置顺序决定拦截顺序;
  • 全局通知:名称以 * 结尾(如 globalAdvisor*),表示从容器中获取所有类型匹配的 Advisor,适用于全局生效的通知(如全局日志);
  • 原型拦截器处理:通过 PrototypePlaceholderAdvisor 占位,避免初始化通知器链时提前创建原型拦截器(原型 Bean 应在每次代理调用时创建)。

步骤 2:getSingletonInstance()—— 生成单例代理实例

单例代理的生成逻辑是 ProxyFactoryBean 的核心,包含 “确定代理接口→创建 AOP 代理→生成代理对象” 三个子步骤:

源码逻辑拆解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) { // 首次创建,缓存未命中
// 1. 刷新目标源(获取目标对象,如配置的 target 或 targetName 对应的 Bean)
this.targetSource = freshTargetSource();

// 2. 自动检测代理接口(若未显式配置 interfaces 且 proxyTargetClass=false)
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
Class<?> targetClass = getTargetClass(); // 获取目标对象的类
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("无法确定目标类");
}
// 为代理对象设置接口(代理目标类实现的所有接口)
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}

// 3. 冻结 AOP 配置(避免后续修改影响已生成的代理)
super.setFrozen(this.freezeProxy);

// 4. 核心:创建 AOP 代理并生成代理对象
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
关键逻辑说明
  • freshTargetSource():解析 targettargetName 属性,获取目标对象(被代理的原始对象),封装为 TargetSource(Spring AOP 中目标对象的统一封装,支持懒加载、原型目标等);
  • 接口自动检测:若未显式配置 interfaces(代理接口),且未开启 proxyTargetClass(强制代理目标类),则自动将目标类实现的所有接口作为代理接口(为 JDK 动态代理做准备);
  • getProxy(createAopProxy()):先通过 createAopProxy() 选择代理类型(JDK/CGLIB),再调用 AopProxy.getProxy() 生成最终代理对象。

步骤 3:createAopProxy()—— 选择代理类型(JDK/CGLIB)

createAopProxy() 是 AOP 代理类型选择的核心,由 DefaultAopProxyFactory(默认实现)完成,决策逻辑基于 “目标对象类型” 和 “配置参数”:

源码逻辑拆解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// ProxyFactoryBean 中调用(继承自 AdvisedSupport)
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate(); // 激活 AOP 配置
}
// 委托给 AopProxyFactory 创建 AopProxy(默认是 DefaultAopProxyFactory)
return getAopProxyFactory().createAopProxy(this);
}

// DefaultAopProxyFactory#createAopProxy(核心决策逻辑)
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 决策条件:是否优化代理、是否强制代理目标类、是否无用户指定的代理接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass(); // 获取目标类
if (targetClass == null) {
throw new AopConfigException("无法确定目标类,代理创建失败");
}

// 条件1:若目标类是接口 或 本身是代理类 → 使用 JDK 动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}

// 条件2:否则 → 使用 CGLIB 代理(默认用 ObjenesisCglibAopProxy,解决无参构造器问题)
return new ObjenesisCglibAopProxy(config);
}
// 其他情况(有显式代理接口且未强制代理目标类)→ 使用 JDK 动态代理
else {
return new JdkDynamicAopProxy(config);
}
}
决策条件详解
条件参数 作用 示例场景
isOptimize() 是否优化代理(默认 false) 开启后优先选择 CGLIB(性能略优)
isProxyTargetClass() 是否强制代理目标类(默认 false) 设为 true 时,无论是否有接口都用 CGLIB
hasNoUserSuppliedProxyInterfaces() 是否无用户指定的代理接口 目标类无接口,或未显式配置 interfaces
核心结论
  • JDK 动态代理:适用于 “目标类实现接口” 的场景,基于接口生成代理;
  • CGLIB 代理:适用于 “目标类无接口” 或 “强制代理目标类”(proxyTargetClass=true)的场景,基于继承目标类生成代理。

步骤 4:生成具体代理(JDK vs CGLIB)

根据 createAopProxy() 的决策结果,分别由 JdkDynamicAopProxyObjenesisCglibAopProxy 生成代理对象。

(1)JDK 动态代理:JdkDynamicAopProxy.getProxy()

JDK 动态代理基于 java.lang.reflect.Proxy 实现,要求目标类必须实现接口,代理对象是接口的实现类。

源码逻辑拆解
1
2
3
4
5
6
7
8
public Object getProxy(ClassLoader classLoader) {
// 1. 补全代理接口(添加 Spring 内部接口,如 Advised,用于暴露 AOP 配置)
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 2. 检查是否需要重写 equals() 和 hashCode()(若接口中定义了这两个方法)
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 3. 生成 JDK 代理对象(this 是 InvocationHandler,负责拦截方法调用)
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
关键逻辑说明
  • completeProxiedInterfaces():除了目标接口,还会添加 Advised 接口(Spring AOP 定义的接口),让代理对象可被强制转为 Advised,从而动态修改 AOP 配置(如添加通知);
  • InvocationHandler 角色JdkDynamicAopProxy 实现了 InvocationHandler 接口,其 invoke() 方法是 AOP 拦截的核心 —— 当代理对象的方法被调用时,会触发 invoke(),执行通知链逻辑后再调用目标方法。
(2)CGLIB 代理:ObjenesisCglibAopProxy.getProxy()

CGLIB 代理基于字节码生成技术(继承目标类),无需目标类实现接口,但无法代理 final 类或 final 方法(final 类无法被继承,final 方法无法被重写)。Spring 用 Objenesis 优化 CGLIB,解决了 “目标类无无参构造器” 的问题。

源码逻辑拆解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public Object getProxy(ClassLoader classLoader) {
try {
// 1. 获取目标类(若目标类本身是 CGLIB 代理,取其父类)
Class<?> rootClass = this.advised.getTargetClass();
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
// 继承目标类的接口
for (Class<?> ifc : rootClass.getInterfaces()) {
this.advised.addInterface(ifc);
}
}

// 2. 配置 CGLIB Enhancer(CGLIB 生成代理的核心类)
Enhancer enhancer = createEnhancer();
enhancer.setClassLoader(classLoader);
enhancer.setSuperclass(proxySuperClass); // 设置代理类的父类(目标类)
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); // 设置代理接口
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); // 代理类命名策略(如 "UserService$$EnhancerBySpringCGLIB$$xxx")

// 3. 设置回调(CGLIB 拦截方法的核心,对应 AOP 通知链)
Callback[] callbacks = getCallbacks(rootClass);
enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised, ...)); // 回调过滤器(决定哪个方法用哪个回调)
enhancer.setCallbackTypes(ClassUtils.getClassNames(callbacks));

// 4. 生成代理类并创建实例
return createProxyClassAndInstance(enhancer, callbacks);
} catch (Throwable ex) {
throw new AopConfigException("CGLIB 代理生成失败", ex);
}
}
关键逻辑说明
  • Enhancer:CGLIB 生成代理的核心工具类,通过 setSuperclass() 指定父类(目标类),生成的代理类会继承目标类;
  • 回调(Callback):CGLIB 通过回调拦截方法调用,getCallbacks() 会生成包含 “通知链执行逻辑” 的回调对象(如 DynamicAdvisedInterceptor),当代理方法被调用时,回调会触发通知链执行;
  • Objenesis 优化:传统 CGLIB 要求目标类有无参构造器,ObjenesisCglibAopProxy 通过 Objenesis 绕过构造器,直接生成实例,解决了无参构造器依赖问题。

JDK 动态代理 vs CGLIB 代理:核心区别与适用场景

维度 JDK 动态代理 CGLIB 代理
底层技术 JDK 反射 API(Proxy + InvocationHandler ASM 字节码生成(继承目标类)
依赖条件 目标类必须实现接口 目标类不能是 final,方法不能是 final
代理对象类型 接口实现类(与目标类同级) 目标类的子类(is-a 关系)
性能 方法调用时反射开销略高 字节码增强,方法调用开销低(初始化耗时略高)
适用场景 目标类实现接口(如 Service 接口) 目标类无接口、需代理类方法(如工具类)

ProxyFactoryBean 的配置与应用

ProxyFactoryBean 需通过 XML 或注解配置核心属性,才能生成符合需求的 AOP 代理。以下是典型的 XML 配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 1. 目标对象(被代理的原始 Bean) -->
<bean id="userService" class="com.example.UserService">
<property name="userDao" ref="userDao"/>
</bean>

<!-- 2. 通知(拦截逻辑,如日志拦截器) -->
<bean id="logInterceptor" class="com.example.LogInterceptor"/>

<!-- 3. ProxyFactoryBean:生成 AOP 代理 -->
<bean id="userServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 核心配置1:目标对象(被代理的 Bean) -->
<property name="target" ref="userService"/>
<!-- 核心配置2:拦截器/通知列表(顺序决定拦截顺序) -->
<property name="interceptorNames" value="logInterceptor"/>
<!-- 核心配置3:代理类型(true=强制 CGLIB,false=默认 JDK) -->
<property name="proxyTargetClass" value="false"/>
<!-- 可选:显式指定代理接口(若未配置,自动检测) -->
<property name="interfaces" value="com.example.UserService"/>
<!-- 可选:作用域(默认 singleton,原型设为 prototype) -->
<property name="singleton" value="true"/>
</bean>
  • target:指向被代理的目标对象;
  • interceptorNames:通知 / 拦截器的 Bean 名称列表(逗号分隔);
  • proxyTargetClass:是否强制使用 CGLIB 代理(true 时忽略接口,直接代理类);
  • interfaces:显式指定代理接口(适用于目标类实现多个接口,需指定部分接口代理的场景)。

使用时,从容器获取 userServiceProxy 即可得到 AOP 代理对象,调用其方法会自动触发 logInterceptor 的拦截逻辑。

ProxyFactoryBean 与高层 AOP 方式的关系

我们日常使用的 @AspectJ(如 @Before@After)是 Spring AOP 的高层封装,其底层仍依赖 ProxyFactoryBean 类似的逻辑:

  1. @EnableAspectJAutoProxy 注解会注册 AnnotationAwareAspectJAutoProxyCreator(BeanPostProcessor);
  2. 该处理器会扫描 @Aspect 注解的类,解析切入点和通知,自动生成 Advisor 链;
  3. 最终通过 ProxyFactory(ProxyFactoryBean 的非 FactoryBean 版本)生成 AOP 代理,代理类型选择逻辑与 ProxyFactoryBean 一致。

简言之:ProxyFactoryBean 是 Spring AOP 代理生成的底层实现,高层注解是对其配置和使用的简化

总结

ProxyFactoryBean 是 Spring AOP 与 IOC 容器融合的核心,其核心价值在于 “将 AOP 代理的创建逻辑纳入 IOC 管理”,通过配置驱动生成代理对象。其核心流程可概括为:

  1. 入口getObject() 触发代理创建;
  2. 初始化initializeAdvisorChain() 构建通知器链;
  3. 决策createAopProxy() 选择 JDK/CGLIB 代理;
  4. 生成AopProxy.getProxy() 生成最终代理对象

欢迎关注我的其它发布渠道