Spring AOP 和 Aware:在Bean实例化后-调用BeanPostProcessor开始工作!在初始化方法执行之前!

Spring AOP 和 Aware 的实现阶段解析

Spring 框架是 Java 开发中最流行的依赖注入和面向切面编程框架之一。在 Spring 容器中,AOP 和 Aware 接口是两个非常重要的功能,它们分别用于实现横切关注点和让 Bean 感知容器环境。那么,这两个功能具体是在哪个阶段实现的呢?是在 BeanPostProcessor 中实现的,还是在 finishBeanFactoryInitialization 中完成的?本文将深入探讨这个问题,并结合 Spring 的 Bean 生命周期进行详细分析。

Spring 容器启动和 Bean 生命周期概述

在分析 AOP 和 Aware 的实现之前,我们先简要回顾一下 Spring 容器的启动流程和 Bean 的生命周期。Spring 容器的启动主要分为以下几个阶段:

  1. 加载配置文件或扫描注解 :Spring 通过 ClassPathXmlApplicationContextAnnotationConfigApplicationContext 加载 Bean 定义。
  2. BeanFactory 初始化 :创建 DefaultListableBeanFactory,注册 Bean 定义。
  3. BeanFactory 后处理 :调用 BeanFactoryPostProcessor,调整 Bean 定义。
  4. Bean 实例化和初始化
    • 实例化 Bean(instantiateBean)。
    • 属性填充(populateBean)。
    • 调用 BeanPostProcessor 的前置和后置处理。
    • 执行初始化方法(InitializingBean.afterPropertiesSetinit-method)。
  5. 完成 BeanFactory 初始化finishBeanFactoryInitialization,实例化所有非懒加载的单例 Bean。
  6. 容器就绪:Spring 容器启动完成,Bean 可供使用。

Bean 的生命周期中,BeanPostProcessor 是一个关键组件,它允许在 Bean 初始化前后插入自定义逻辑。而 finishBeanFactoryInitialization 是容器启动的最后一步,用于实例化所有单例 Bean。

接下来,我们分别分析 Aware 和 AOP 的实现时机。

Aware 接口的实现阶段

Aware 接口的作用

Aware 是一组标记接口(如 ApplicationContextAwareBeanNameAware 等),用于让 Bean 感知 Spring 容器的某些特性。例如:

  • ApplicationContextAware:让 Bean 获取 ApplicationContext
  • BeanNameAware:让 Bean 知道自己的名称。

这些接口的实现依赖于 Spring 的依赖注入机制,具体来说,是在 Bean 初始化阶段完成的。

Aware 的实现时机

Aware 接口的实现发生在 Bean 的初始化阶段 ,具体由 BeanPostProcessor 负责。Spring 提供了一个内置的 BeanPostProcessor 实现类:ApplicationContextAwareProcessor,它专门处理所有 Aware 接口。

在 Bean 生命周期中,ApplicationContextAwareProcessor 的逻辑如下:

  1. 实例化 Bean:通过构造方法创建 Bean 实例。
  2. 属性填充 :通过 populateBean 注入依赖。
  3. 调用 BeanPostProcessor 的前置处理postProcessBeforeInitialization 方法被调用。
    • 在这一步,ApplicationContextAwareProcessor 检查 Bean 是否实现了某个 Aware 接口。如果是,它会调用相应的 setter 方法注入容器资源。例如:
      • 如果 Bean 实现了 ApplicationContextAware,则调用 setApplicationContext
      • 如果 Bean 实现了 BeanNameAware,则调用 setBeanName
  4. 初始化方法执行 :调用 afterPropertiesSetinit-method
  5. 调用 BeanPostProcessor 的后置处理postProcessAfterInitialization

因此,Aware 接口的实现是在 BeanPostProcessorpostProcessBeforeInitialization 阶段完成的 ,而不是在 finishBeanFactoryInitialization 中。finishBeanFactoryInitialization 只是触发了所有非懒加载单例 Bean 的实例化和初始化流程,而 Aware 的具体注入逻辑是由 BeanPostProcessor 执行的。

Spring AOP 的实现阶段

Spring AOP 的作用

Spring AOP 用于实现横切关注点(如日志、事务管理等),通过代理模式(JDK 动态代理或 CGLIB)增强目标 Bean 的功能。AOP 的核心是创建代理对象,并将切面逻辑织入目标 Bean。

AOP 的实现时机

Spring AOP 的实现同样依赖于 BeanPostProcessor,具体由 AbstractAutoProxyCreator(如 AnnotationAwareAspectJAutoProxyCreator)完成。这个类是 Spring AOP 的核心组件,负责在 Bean 初始化后创建代理对象。

AOP 的实现过程如下:

  1. 实例化 Bean:创建目标 Bean 的实例。
  2. 属性填充:注入依赖。
  3. 调用 BeanPostProcessor 的前置处理postProcessBeforeInitialization,此时 AOP 尚未介入。
  4. 初始化方法执行 :调用 afterPropertiesSetinit-method
  5. 调用 BeanPostProcessor 的后置处理postProcessAfterInitialization
    • 在这一步,AbstractAutoProxyCreator 检查 Bean 是否需要应用切面(根据 @Aspect 和切点表达式)。
    • 如果需要,它会创建代理对象(JDK 动态代理或 CGLIB),将切面逻辑织入,并返回代理对象替换原始 Bean。

因此,Spring AOP 的实现是在 BeanPostProcessorpostProcessAfterInitialization 阶段完成的。与 Aware 不同,AOP 的织入发生在初始化之后,因为它需要对完整的 Bean 进行增强。

同样,finishBeanFactoryInitialization 只是触发了单例 Bean 的实例化和初始化流程,而 AOP 的代理创建是由 BeanPostProcessor 在每个 Bean 初始化后执行的。

BeanPostProcessor vs finishBeanFactoryInitialization

从上面的分析可以看出:

  • BeanPostProcessor 是 Spring 提供的一个扩展点,用于在 Bean 初始化前后插入自定义逻辑。Aware 和 AOP 的实现都依赖于这个机制:
    • Aware:通过 postProcessBeforeInitialization 注入容器资源。
    • AOP:通过 postProcessAfterInitialization 创建代理对象。
  • finishBeanFactoryInitialization 是 Spring 容器启动的一个阶段,负责实例化所有非懒加载的单例 Bean。它触发了 Bean 的创建和初始化流程,但具体的 Aware 注入和 AOP 织入是由 BeanPostProcessor 在每个 Bean 的生命周期中完成的。

简单来说,finishBeanFactoryInitialization 是宏观上的容器初始化步骤,而 BeanPostProcessor 是微观上的 Bean 级别处理工具。Aware 和 AOP 的实现属于后者。

总结

  • Aware 接口 :在 BeanPostProcessorpostProcessBeforeInitialization 阶段实现,由 ApplicationContextAwareProcessor 处理。
  • Spring AOP :在 BeanPostProcessorpostProcessAfterInitialization 阶段实现,由 AbstractAutoProxyCreator 创建代理对象。
  • finishBeanFactoryInitialization:仅负责触发单例 Bean 的实例化和初始化流程,不直接实现 Aware 或 AOP。

通过这种设计,Spring 既保证了容器资源的注入(Aware),又实现了灵活的横切逻辑织入(AOP),体现了其高度模块化和可扩展的特性。希望这篇文章能帮助你更好地理解 Spring 的内部机制!

相关推荐
Asthenia04129 小时前
什么是消除直接左递归 - 编译原理解析
后端
Asthenia04129 小时前
什么是自上而下分析 - 编译原理剖析
后端
Asthenia041210 小时前
什么是语法分析 - 编译原理基础
后端
Asthenia041210 小时前
理解词法分析与LEX:编译器的守门人
后端
uhakadotcom10 小时前
视频直播与视频点播:基础知识与应用场景
后端·面试·架构
Asthenia041211 小时前
Spring扩展点与工具类获取容器Bean-基于ApplicationContextAware实现非IOC容器中调用IOC的Bean
后端
bobz96511 小时前
ovs patch port 对比 veth pair
后端
Asthenia041211 小时前
Java受检异常与非受检异常分析
后端