Spring AOP 代理对象生成机制详解

dalang · · 122 次点击 · · 开始浏览    
#### **1. Spring Bean 生命周期概述** Spring Bean 的创建过程主要分为以下几个阶段: 1. **实例化**:通过构造器或工厂方法创建 Bean 的原始对象。 2. **属性填充(DI)**:注入依赖的属性和其他 Bean。 3. **初始化**: • **BeanPostProcessor 的前置处理**(`postProcessBeforeInitialization`)。 • **自定义初始化方法**(如 `@PostConstruct`、`InitializingBean`)。(依次如 @PostConstruct、InitializingBean的afterPropertiesSet, init-method) • **BeanPostProcessor 的后置处理**(`postProcessAfterInitialization`)。 #### **2. AOP 代理生成的触发时机** **AOP 代理的生成发生在 Bean 的初始化阶段之后**,具体由 `BeanPostProcessor` 的 `postProcessAfterInitialization` 方法触发。关键步骤如下: • **触发点**:当 Spring 容器完成 Bean 的实例化、属性注入和自定义初始化后,会遍历所有 `BeanPostProcessor`,调用其 `postProcessAfterInitialization` 方法。 • **核心类**:`AbstractAutoProxyCreator`(AOP 代理的基类)在此阶段检查 Bean 是否需要被代理。若需要,则动态生成代理对象。 #### **3. 源码解析与流程验证** **关键源码**(`AbstractAutoProxyCreator#postProcessAfterInitialization`): ```java public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { // 生成缓存键(用于避免重复代理) Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 若 Bean 需要代理,则生成代理对象 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } ``` • **`wrapIfNecessary` 逻辑**: • 检查 Bean 是否已存在代理。 • 匹配当前 Bean 是否符合切面规则(如 `@Aspect` 定义的切点)。 • 若匹配,则通过 JDK 动态代理或 CGLIB 生成代理对象。 #### **4. 后置处理器的“惰性”特性** • **按需触发**:并非所有 Bean 都会触发 AOP 代理生成。**仅当 Bean 匹配到至少一个切面规则时,才会生成代理**,体现“惰性”。 • **缓存机制**:已处理的 Bean 会被缓存(如 `targetSourcedBeans`),避免重复检查与代理生成。 #### **5. 生成代理的具体操作** • **匹配切面**:通过 `Pointcut` 匹配 Bean 的方法是否需要增强。 • **选择代理方式**: • **JDK 动态代理**:当 Bean 实现了接口。 • **CGLIB 代理**:当 Bean 未实现接口或强制使用 CGLIB(`proxyTargetClass=true`)。 • **代理对象替换**:容器用代理对象替换原始 Bean,后续操作均基于代理。 #### **6. 示例场景** **场景**:Bean `UserService` 被 `@Transactional` 标记。 1. **实例化**:创建 `UserService` 原始对象。 2. **属性注入**:填充 `UserRepository` 依赖。 3. **初始化**: • 执行 `@PostConstruct` 方法。 • `AbstractAutoProxyCreator` 检测到 `UserService` 需事务管理,生成代理对象 `UserService$$EnhancerBySpringCGLIB`。 4. **代理生效**:容器中存储的 `UserService` 实为代理对象,后续调用其方法时,代理会介入执行事务逻辑。 #### **7. 特殊情况处理** • **循环依赖中的代理**:若存在循环依赖,Spring 会在属性注入阶段提前通过 `ObjectFactory` 生成代理(参考三级缓存机制),但最终仍会在 `postProcessAfterInitialization` 确认代理一致性。 • **AOP 与初始化顺序**:若自定义初始化方法(如 `@PostConstruct`)中调用了代理方法,此时可能因代理未生成而失效。需确保初始化方法不依赖代理增强的逻辑。 --- ### **总结** | **维度** | **说明** | |-------------------------|-------------------------------------------------------------------------| | **代理生成时机** | Bean 初始化阶段后,由 `postProcessAfterInitialization` 触发。 | | **触发操作** | `BeanPostProcessor` 遍历检查,按需生成代理。 | | **后置处理器惰性** | 是,仅当 Bean 匹配切面规则时才生成代理。 | | **代理替换机制** | 容器用代理对象替换原始 Bean,后续依赖注入和调用均基于代理。 | | **循环依赖中的处理** | 通过三级缓存提前暴露代理工厂,确保循环依赖中注入正确的代理对象。 | **结论**: Spring AOP 代理对象在 Bean **初始化完成后**由 `AbstractAutoProxyCreator` 动态生成,此过程具有“按需触发”的惰性特征,确保仅增强符合切面规则的 Bean。理解此机制有助于优化 AOP 使用和排查代理相关问题。
122 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传