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 的内部机制!

相关推荐
swordbob25 分钟前
CAP 定理:为什么不能同时实现 C、A、P?
开发语言·后端·spring
lazy H1 小时前
Spring Boot 项目如何连接 Redis?新手入门配置和常见错误总结
ide·spring boot·redis·后端·学习·intellij-idea
SXJR1 小时前
spring boot + langchain4j +milvus实现向量存储
java·spring boot·后端·大模型·milvus·rag·langchain4j
王木风1 小时前
Spring Boot + LLM 工程化:把短视频流水线拆成 16 个独立角色的踩坑记录
人工智能·spring boot·后端·开源·新媒体运营·音视频·agent
武子康1 小时前
Java-27 深入浅出 Spring - 实现简易Ioc-03 在上节的业务下手动实现IoC 从 XML 配置到 BeanFactory 反射注入
java·后端·mybatis
月光刺眼1 小时前
Bun + TypeScript 后端入门:从类型约束到 LLM API 调用
后端·typescript
万岳科技1 小时前
教育培训系统开发流程详解:平台建设关键环节解析
数据库·后端·学习
Java编程爱好者1 小时前
服务里的 Redis 锁惊群问题:一次本地合流优化实践
后端
Nturmoils1 小时前
线上修一批脏数据,先别急着全量重来
数据库·后端
飞天狗1111 小时前
零基础JavaWeb入门——第五课第一小节:九大内置对象 · 第1个:request(请求对象)
java·开发语言·前端·后端·servlet