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

相关推荐
程序员爱钓鱼12 分钟前
匿名函数与闭包(Anonymous Functions and Closures)-《Go语言实战指南》原创
后端·golang
言之。1 小时前
Go 语言中接口类型转换为具体类型
开发语言·后端·golang
diving deep2 小时前
XML简要介绍
xml·java·后端
编程乐学(Arfan开发工程师)4 小时前
06、基础入门-SpringBoot-依赖管理特性
android·spring boot·后端
编程乐学(Arfan开发工程师)4 小时前
05、基础入门-SpringBoot-HelloWorld
java·spring boot·后端
橘子海全栈攻城狮4 小时前
【源码+文档+调试讲解】党员之家服务系统小程序1
java·开发语言·spring boot·后端·小程序·旅游
冼紫菜5 小时前
Java开发中使用 RabbitMQ 入门到进阶详解(含注解方式、JSON配置)
java·spring boot·后端·rabbitmq·springcloud
boring_1115 小时前
Apache Pulsar 消息、流、存储的融合
分布式·后端
源码方舟7 小时前
SpringBoot + Shiro + JWT 实现认证与授权完整方案实现
java·spring boot·后端
热河暖男11 小时前
【实战解决方案】Spring Boot+Redisson构建高并发Excel导出服务,彻底解决系统阻塞难题
spring boot·后端·excel