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 代理工厂”,其核心职责是:
- 整合 AOP 配置:管理通知(Advice)、切入点(Pointcut)、目标对象(Target)等 AOP 核心元素;
- 构建通知器链:将配置的拦截器 / 通知组装成
Advisor链(AOP 拦截逻辑的执行顺序由链决定); - 生成代理对象:根据目标对象类型(接口 / 类)自动选择 JDK 动态代理或 CGLIB 代理,最终通过
getObject()方法向容器暴露代理对象。
关键继承与实现关系
ProxyFactoryBean 继承了 AdvisedSupport(封装 AOP 配置的核心类),实现了 FactoryBean<Object>(IOC 容器的工厂 Bean 接口),其类结构如下:
ProxyFactoryBean
├─ 继承:AdvisedSupport(管理 Advisor、TargetSource、代理配置)
└─ 实现:FactoryBean<Object>(通过 getObject() 生成代理对象)
- AdvisedSupport:存储 AOP 代理的所有配置(目标对象、通知器链、代理类型等),是 AOP 代理生成的 “数据源”;
- FactoryBean:让 ProxyFactoryBean 成为 IOC 中的 “工厂 Bean”—— 容器获取的不是 ProxyFactoryBean 本身,而是其
getObject()方法返回的AOP 代理对象。
ProxyFactoryBean 核心流程:从配置到代理生成

ProxyFactoryBean 的核心入口是 getObject() 方法(实现自 FactoryBean),整个流程可分为 “初始化通知器链→生成代理实例→选择代理类型→创建具体代理” 四步。
入口方法:getObject()—— 触发代理创建
getObject() 是 ProxyFactoryBean 的核心方法,负责判断代理的作用域(单例 / 原型),并调用对应的逻辑生成代理对象:
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 链。
源码逻辑拆解
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 代理→生成代理对象” 三个子步骤:
源码逻辑拆解
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():解析target或targetName属性,获取目标对象(被代理的原始对象),封装为TargetSource(Spring AOP 中目标对象的统一封装,支持懒加载、原型目标等);- 接口自动检测:若未显式配置
interfaces(代理接口),且未开启proxyTargetClass(强制代理目标类),则自动将目标类实现的所有接口作为代理接口(为 JDK 动态代理做准备); getProxy(createAopProxy()):先通过createAopProxy()选择代理类型(JDK/CGLIB),再调用AopProxy.getProxy()生成最终代理对象。
步骤 3:createAopProxy()—— 选择代理类型(JDK/CGLIB)
createAopProxy() 是 AOP 代理类型选择的核心,由 DefaultAopProxyFactory(默认实现)完成,决策逻辑基于 “目标对象类型” 和 “配置参数”:
源码逻辑拆解
// 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() 的决策结果,分别由 JdkDynamicAopProxy 和 ObjenesisCglibAopProxy 生成代理对象。
(1)JDK 动态代理:JdkDynamicAopProxy.getProxy()
JDK 动态代理基于 java.lang.reflect.Proxy 实现,要求目标类必须实现接口,代理对象是接口的实现类。
源码逻辑拆解
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,解决了 “目标类无无参构造器” 的问题。
源码逻辑拆解
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. 目标对象(被代理的原始 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 类似的逻辑:
@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()生成最终代理对象