Spring ProxyFactoryBean 深度解析:AOP 代理的底层实现核心
ProxyFactoryBean 是 Spring AOP 与 IOC 容器融合的关键组件,它实现了 FactoryBean 接口,专门用于在 IOC 环境中创建 AOP 代理对象。不同于 @AspectJ 等高层注解驱动的 AOP 方式,ProxyFactoryBean 是更底层的实现,直接暴露了 AOP 代理的配置细节(如通知器链、代理类型选择)。从 “核心定位→源码流程→代理生成逻辑→JDK/CGLIB 对比” 四个维度,彻底讲透 ProxyFactoryBean 如何完成 AOP 代理的创建。
ProxyFactoryBean 的核心定位
在 Spring AOP 体系中,ProxyFactoryBean 的角色是 “IOC 容器中的 AOP 代理工厂”,其核心职责是:
- 整合 AOP 配置:管理通知(Advice)、切入点(Pointcut)、目标对象(Target)等 AOP 核心元素;
- 构建通知器链:将配置的拦截器 / 通知组装成
Advisor链(AOP 拦截逻辑的执行顺序由链决定); - 生成代理对象:根据目标对象类型(接口 / 类)自动选择 JDK 动态代理或 CGLIB 代理,最终通过
getObject()方法向容器暴露代理对象。
关键继承与实现关系
ProxyFactoryBean 继承了 AdvisedSupport(封装 AOP 配置的核心类),实现了 FactoryBean<Object>(IOC 容器的工厂 Bean 接口),其类结构如下:
1 | ProxyFactoryBean |
- AdvisedSupport:存储 AOP 代理的所有配置(目标对象、通知器链、代理类型等),是 AOP 代理生成的 “数据源”;
- FactoryBean:让 ProxyFactoryBean 成为 IOC 中的 “工厂 Bean”—— 容器获取的不是 ProxyFactoryBean 本身,而是其
getObject()方法返回的AOP 代理对象。
ProxyFactoryBean 核心流程:从配置到代理生成

ProxyFactoryBean 的核心入口是 getObject() 方法(实现自 FactoryBean),整个流程可分为 “初始化通知器链→生成代理实例→选择代理类型→创建具体代理” 四步。
入口方法:getObject()—— 触发代理创建
getObject() 是 ProxyFactoryBean 的核心方法,负责判断代理的作用域(单例 / 原型),并调用对应的逻辑生成代理对象:
1 | public Object getObject() throws BeansException { |
- 单例代理:默认模式,代理对象创建后缓存到
singletonInstance字段,容器生命周期内仅创建一次; - 原型代理:每次获取 Bean 时都重新创建代理,适用于目标对象为原型的场景。
步骤 1:initializeAdvisorChain()—— 构建 AOP 通知器链
AOP 代理的核心是 “拦截逻辑的执行”,而通知器链(Advisor Chain)是拦截逻辑的组织形式(每个 Advisor 包含 “切入点 + 通知”)。initializeAdvisorChain() 的作用是将配置的 interceptorNames(拦截器 Bean 名称列表)转为实际的 Advisor 链。
源码逻辑拆解
1 | private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException { |
关键逻辑说明
interceptorNames:ProxyFactoryBean 的核心配置属性,存储拦截器 / 通知的 Bean 名称(如["logInterceptor", "transactionInterceptor"]),配置顺序决定拦截顺序;- 全局通知:名称以
*结尾(如globalAdvisor*),表示从容器中获取所有类型匹配的Advisor,适用于全局生效的通知(如全局日志); - 原型拦截器处理:通过
PrototypePlaceholderAdvisor占位,避免初始化通知器链时提前创建原型拦截器(原型 Bean 应在每次代理调用时创建)。
步骤 2:getSingletonInstance()—— 生成单例代理实例
单例代理的生成逻辑是 ProxyFactoryBean 的核心,包含 “确定代理接口→创建 AOP 代理→生成代理对象” 三个子步骤:
源码逻辑拆解
1 | private synchronized Object getSingletonInstance() { |
关键逻辑说明
freshTargetSource():解析target或targetName属性,获取目标对象(被代理的原始对象),封装为TargetSource(Spring AOP 中目标对象的统一封装,支持懒加载、原型目标等);- 接口自动检测:若未显式配置
interfaces(代理接口),且未开启proxyTargetClass(强制代理目标类),则自动将目标类实现的所有接口作为代理接口(为 JDK 动态代理做准备); getProxy(createAopProxy()):先通过createAopProxy()选择代理类型(JDK/CGLIB),再调用AopProxy.getProxy()生成最终代理对象。
步骤 3:createAopProxy()—— 选择代理类型(JDK/CGLIB)
createAopProxy() 是 AOP 代理类型选择的核心,由 DefaultAopProxyFactory(默认实现)完成,决策逻辑基于 “目标对象类型” 和 “配置参数”:
源码逻辑拆解
1 | // ProxyFactoryBean 中调用(继承自 AdvisedSupport) |
决策条件详解
| 条件参数 | 作用 | 示例场景 |
|---|---|---|
isOptimize() |
是否优化代理(默认 false) | 开启后优先选择 CGLIB(性能略优) |
isProxyTargetClass() |
是否强制代理目标类(默认 false) | 设为 true 时,无论是否有接口都用 CGLIB |
hasNoUserSuppliedProxyInterfaces() |
是否无用户指定的代理接口 | 目标类无接口,或未显式配置 interfaces |
核心结论
- JDK 动态代理:适用于 “目标类实现接口” 的场景,基于接口生成代理;
- CGLIB 代理:适用于 “目标类无接口” 或 “强制代理目标类”(
proxyTargetClass=true)的场景,基于继承目标类生成代理。
步骤 4:生成具体代理(JDK vs CGLIB)
根据 createAopProxy() 的决策结果,分别由 JdkDynamicAopProxy 和 ObjenesisCglibAopProxy 生成代理对象。
(1)JDK 动态代理:JdkDynamicAopProxy.getProxy()
JDK 动态代理基于 java.lang.reflect.Proxy 实现,要求目标类必须实现接口,代理对象是接口的实现类。
源码逻辑拆解
1 | public Object getProxy(ClassLoader classLoader) { |
关键逻辑说明
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 | public Object getProxy(ClassLoader classLoader) { |
关键逻辑说明
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 | <!-- 1. 目标对象(被代理的原始 Bean) --> |
target:指向被代理的目标对象;interceptorNames:通知 / 拦截器的 Bean 名称列表(逗号分隔);proxyTargetClass:是否强制使用 CGLIB 代理(true时忽略接口,直接代理类);interfaces:显式指定代理接口(适用于目标类实现多个接口,需指定部分接口代理的场景)。
使用时,从容器获取 userServiceProxy 即可得到 AOP 代理对象,调用其方法会自动触发 logInterceptor 的拦截逻辑。
ProxyFactoryBean 与高层 AOP 方式的关系
我们日常使用的 @AspectJ(如 @Before、@After)是 Spring AOP 的高层封装,其底层仍依赖 ProxyFactoryBean 类似的逻辑:
@EnableAspectJAutoProxy注解会注册AnnotationAwareAspectJAutoProxyCreator(BeanPostProcessor);- 该处理器会扫描
@Aspect注解的类,解析切入点和通知,自动生成Advisor链; - 最终通过
ProxyFactory(ProxyFactoryBean 的非 FactoryBean 版本)生成 AOP 代理,代理类型选择逻辑与 ProxyFactoryBean 一致。
简言之:ProxyFactoryBean 是 Spring AOP 代理生成的底层实现,高层注解是对其配置和使用的简化。
总结
ProxyFactoryBean 是 Spring AOP 与 IOC 容器融合的核心,其核心价值在于 “将 AOP 代理的创建逻辑纳入 IOC 管理”,通过配置驱动生成代理对象。其核心流程可概括为:
- 入口:
getObject()触发代理创建; - 初始化:
initializeAdvisorChain()构建通知器链; - 决策:
createAopProxy()选择 JDK/CGLIB 代理; - 生成:
AopProxy.getProxy()生成最终代理对象