Spring 动态代理、注解、反射、AOP、Bean 混讲详解
一、Spring Bean 生命周期与 AOP 代理创建正常流程
1. 组件扫描与 Bean 定义注册
Spring 启动时,会扫描类路径(classpath)下的所有字节码文件,识别带有特定注解(如 @Component及其派生注解 @Service、@Repository、@Controller等)的类。Spring 会为每个符合条件的类创建一个 BeanDefinition 对象,其中包含了该类的元数据信息(如类名、作用域、是否懒加载、依赖关系等)。这些 BeanDefinition 由 BeanFactory 统一管理。
2. 实例化 Bean
Spring 会为每个非懒加载的单例 Bean 调用其构造函数,创建一个普通的 Java 对象实例。这个实例在 Spring 中被称为 Bean。Bean 与普通 new出来的对象的本质区别在于:Bean 的完整生命周期由 Spring 容器管理,包括依赖注入、初始化和销毁等,而普通对象则需开发者手动管理。实例化顺序由依赖关系决定。如果A依赖B,则B会先被实例化。这个顺序是由Bean之间的依赖关系决定的。
3. 依赖注入(填充属性)
Spring 检查当前 Bean 的各个成员变量、setter 方法等,如果发现标有 @Autowired等注解,就会从容器中找到对应的依赖 Bean,并将其注入到当前 Bean 的对应属性中。这一步确保了 Bean 之间的依赖关系被正确建立。
4. BeanPostProcessor 的前置处理
此时,Spring 会调用所有 BeanPostProcessor 的 postProcessBeforeInitialization()方法,允许在 Bean 初始化之前执行一些自定义逻辑。
5. 初始化
Spring 会执行 Bean 的初始化回调方法,主要包括:
- 通过
@PostConstruct注解标记的方法; - 实现了
InitializingBean接口的afterPropertiesSet()方法; - 在 Bean 定义中指定的自定义
init-method方法。
6. BeanPostProcessor 的后置处理与 AOP 代理创建
这是 AOP 介入的关键阶段。Spring 会调用所有 BeanPostProcessor 的 postProcessAfterInitialization()方法。其中,AnnotationAwareAspectJAutoProxyCreator会在这里检查当前 Bean 是否需要被 AOP 增强。如果需要,Spring 会为原始 Bean 创建代理对象。代理的创建方式有两种:
- JDK 动态代理:如果目标 Bean 实现了至少一个接口,Spring 会基于接口创建代理对象。代理对象会实现相同的接口,并在方法调用时插入切面逻辑,再通过反射调用原始 Bean 的方法。
- CGLIB 动态代理:如果目标 Bean 没有实现接口,Spring 会通过 CGLIB 生成目标 Bean 的一个子类作为代理对象。代理对象会重写父类的方法,在方法中插入切面逻辑,并通过调用
methodProxy.invokeSuper()来调用父类方法
重要:代理对象内部会持有一个对原始 Bean(即目标对象)的引用,以便在必要时调用原始方法。
7. Bean 注册到单例池
经过上述所有步骤后,Spring 会将最终准备好的 Bean 实例(如果该 Bean 被 AOP 增强,则放入的是代理对象;如果未增强,则放入原始 Bean 本身)放入单例池(singletonObjects)中。注意,单例池中保存的始终是最终对外暴露的实例。如果创建了代理对象,则代理对象会被放入单例池,而原始 Bean 会作为代理对象内部的一个“目标对象”属性被引用,但不会单独作为 Bean 存在于单例池中。
8. 被其他 Bean 依赖注入
当其他 Bean(例如 Controller)需要引用当前 Bean 时,Spring 会从单例池中获取对应的实例。如果该 Bean 有 AOP 代理,则注入的是代理对象;如果没有,则注入的是原始 Bean。这样,当调用方调用该 Bean 的方法时:
- 如果调用的是代理对象,则会先执行切面逻辑,再通过代理对象调用原始 Bean 的方法。
- 如果调用的是原始 Bean,则直接执行其方法。
核心要点总结:
- Bean 的生命周期由 Spring 管理,包括实例化、依赖注入、初始化和销毁。
- AOP 代理的创建是在 BeanPostProcessor 的后置处理阶段 完成的。
- 单例池中保存的 Bean 是最终形态,可能是原始 Bean,也可能是其代理对象。
- 调用方注入的都是从单例池中取出的 Bean,因此 AOP 增强对调用方是透明的。
二、三种场景的完整流程对比
(一) 场景 1: 无循环依赖 + 无 AOP
时序:
1. 开始创建 Bean A
2. 实例化 A → 原始对象
3. 判断 earlySingletonExposure = true → 创建 ObjectFactory
4. 将 ObjectFactory 放入三级缓存
┌─────────────────────────────────────┐
│ 三级缓存: {"A": ObjectFactory} │
│ 二级缓存: {} │
│ 一级缓存: {} │
└─────────────────────────────────────┘
5. 依赖注入 → 无依赖
6. 初始化
7. BeanPostProcessor 后置处理 → 无 AOP
8. 从三级缓存移除 ObjectFactory
9. 放入一级缓存
┌─────────────────────────────────────┐
│ 三级缓存: {} │
│ 二级缓存: {} │
│ 一级缓存: {"A": 原始对象} │
└─────────────────────────────────────┘
注意: ObjectFactory 从未被调用,所以不会放入二级缓存。
(二) 场景 2: 有循环依赖 + 无 AOP
时序:
1. 开始创建 A
2. 实例化 A
3. 将 A 的 ObjectFactory 放入三级缓存
┌─────────────────────────────────────┐
│ 三级缓存: {"A": ObjectFactory(A)} │
└─────────────────────────────────────┘
4. 填充 A 的属性 → 需要 B
5. 开始创建 B
6. 实例化 B
7. 将 B 的 ObjectFactory 放入三级缓存
┌─────────────────────────────────────┐
│ 三级缓存: {"A": OF(A), "B": OF(B)} │
└─────────────────────────────────────┘
8. 填充 B 的属性 → 需要 A
9. 调用 getSingleton("A") → 三级缓存命中
- 调用 A 的 ObjectFactory.getObject()
- 返回 A 的原始对象
- 【关键】将 A 的原始对象放入二级缓存
- 从三级缓存移除 A 的 ObjectFactory
┌─────────────────────────────────────┐
│ 三级缓存: {"B": OF(B)} │
│ 二级缓存: {"A": 原始对象} │
└─────────────────────────────────────┘
10. B 完成初始化
11. 从三级缓存移除 B 的 ObjectFactory
12. 将 B 放入一级缓存
┌─────────────────────────────────────┐
│ 一级缓存: {"B": 原始对象} │
│ 二级缓存: {"A": 原始对象} │
│ 三级缓存: {} │
└─────────────────────────────────────┘
13. 回到 A,完成初始化
14. 从二级缓存移除 A
15. 将 A 放入一级缓存
┌─────────────────────────────────────┐
│ 一级缓存: {"A": 原始对象, "B": 原始对象}│
│ 二级缓存: {} │
│ 三级缓存: {} │
└─────────────────────────────────────┘
(三) 场景 3: 有循环依赖 + 有 AOP
时序:
1. 开始创建 A (@Transactional 需要代理)
2. 实例化 A
3. 将 A 的 ObjectFactory 放入三级缓存
- ObjectFactory 的 getObject() 会调用 getEarlyBeanReference()
┌─────────────────────────────────────┐
│ 三级缓存: {"A": OF(调用getEarlyBeanReference)}│
└─────────────────────────────────────┘
4. 填充 A 的属性 → 需要 B
5. 开始创建 B
6. 实例化 B
7. 将 B 的 ObjectFactory 放入三级缓存
┌─────────────────────────────────────┐
│ 三级缓存: {"A": OF(A), "B": OF(B)} │
└─────────────────────────────────────┘
8. 填充 B 的属性 → 需要 A
9. 调用 getSingleton("A") → 三级缓存命中
- 调用 A 的 ObjectFactory.getObject()
- 执行 getEarlyBeanReference("A")
- 检查 A 是否需要代理 → 是 (@Transactional)
- 创建 A 的代理对象
- 记录到 earlyProxyReferences: {"A": 原始对象}
- 返回 A 的代理对象
- 【关键】将 A 的代理对象放入二级缓存
- 从三级缓存移除 A 的 ObjectFactory
┌─────────────────────────────────────┐
│ 三级缓存: {"B": OF(B)} │
│ 二级缓存: {"A": 代理对象} │
│ earlyProxyReferences: {"A": 原始对象}│
└─────────────────────────────────────┘
10. B 完成初始化
11. BeanPostProcessor 后置处理
- 检查 B 是否在 earlyProxyReferences → 否
- 检查 B 是否需要代理 → 否
12. 从三级缓存移除 B 的 ObjectFactory
13. 将 B 放入一级缓存
┌─────────────────────────────────────┐
│ 一级缓存: {"B": 原始对象} │
│ 二级缓存: {"A": 代理对象} │
│ 三级缓存: {} │
└─────────────────────────────────────┘
14. 回到 A,完成初始化
15. BeanPostProcessor 后置处理
- 检查 A 是否在 earlyProxyReferences → 是
- 从 earlyProxyReferences 移除 A
- 跳过代理创建
16. 处理循环依赖后处理
Object earlySingletonReference = getSingleton("A", false);
// 从二级缓存获取到代理对象
if (earlySingletonReference != null && exposedObject == bean) {
// 用代理对象替换原始对象
exposedObject = earlySingletonReference;
}
17. 从二级缓存移除 A
18. 将 A 的代理对象放入一级缓存
┌─────────────────────────────────────┐
│ 一级缓存: {"A": 代理对象, "B": 原始对象}│
│ 二级缓存: {} │
│ 三级缓存: {} │
└─────────────────────────────────────┘
更多推荐




所有评论(0)