Spring Bean 生命周期

很多刚学 Spring 的朋友,一看到 Bean 生命周期直接头大,又是实例化又是初始化,一堆名词堆在一起,感觉特别绕。其实没那么玄乎,你就把 Bean 理解成 Spring 帮你 new 出来、管理的对象就行,从出生到最后销毁,就是它完整的生命周期。

Bean 的生命周期大体上有四大步: 实例化阶段 → 初始化阶段(属性填充 / Aware / before / InitializingBean / init / after)→ 完成阶段存入单例池

一、Bean 实例化的基本流程

Spring 容器在进行初始化时,会将 xml 配置的的信息封装成一个 BeanDefinition 对象,所有的 BeanDefinition 存储到一个名为 beanDefinitionMap 的 Map 集合中去,Spring 框架在对该 Map 进行遍历,使用反射创建 Bean 实例对象,创建好的 Bean 对象存储在一个名为 singletonObjects 的 Map 集合中,当调用 getBean 方法时则最终从该 Map 集合中取出 Bean 实例对象返回

1.1 Bean 信息定义对象 - BeanDefinition

Bean 信息定义对象 - BeanDefinition

BeanDefinition 存储到一个名为 beanDefinitionMap

对象存储在一个名为 singletonObjects 的 Map

1.2 基本流程四步

  1. 加载 xml 配置文件,解析获取配置中的每个的信息,封装成一个个的 BeanDefinition 对象;
  2. 将 BeanDefinition 存储在一个名为 beanDefinitionMap 的 Map<String,BeanDefinition> 中;
  3. ApplicationContext 底层遍历 beanDefinitionMap,创建 Bean 实例对象;
  4. 创建好的 Bean 实例对象,被存储到一个名为 singletonObjects 的 Map<String,Object> 中;

二、Spring 的后处理器

Spring 的后处理器是 Spring 对外开发的重要扩展点,允许我们介入到 Bean 的整个实例化流程中来,以达到动态注册 BeanDefinition,动态修改 BeanDefinition,以及动态修改 Bean 的作用。Spring 主要有两种后处理器:

  • BeanFactoryPostProcessor:Bean 工厂后处理器,在 BeanDefinitionMap 填充完毕,Bean 实例化之前执行;
  • BeanPostProcessor:Bean 后处理器,一般在 Bean 实例化之后,填充到单例池 singletonObjects 之前执行。

2.1 BeanFactoryPostProcessor

Bean 工厂后处理器 -- BeanFactoryPostProcessor

BeanFactoryPostProcessor 是一个接口规范,实现了该接口的类只要交由 Spring 容器管理的话,那么 Spring 就会回调该接口的方法,用于对 BeanDefinition 注册和修改的功能。

演示修改:

  1. 创建 BeanFactoryPostProcessor 实现类并重写方法
  2. 注入实现类

演示注册:

  1. 创建 BeanFactoryPostProcessor 实现类并重写方法
  2. 注入实现类

2.2 BeanDefinitionRegistryPostProcessor

Bean 工厂后处理器 -- BeanDefinitionRegistryPostProcessor

Spring 提供了一个 BeanFactoryPostProcessor 的子接口 BeanDefinitionRegistryPostProcessor 专门用于注册 BeanDefinition 操作。

java 复制代码
public class MyBeanFactoryPostProcessor2 implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {}

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        BeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClassName("com.apesource.pojo.Student");
        beanDefinitionRegistry.registerBeanDefinition("stu",beanDefinition);
    }
}

2.3 BeanPostProcessor

Bean 后处理器 -- BeanPostProcessor

Bean 被实例化后,到最终缓存到名为 singletonObjects 单例池之前,中间会经过 Bean 的初始化过程,例如:属性的填充、初始方法 init 的执行等,其中有一个对外进行扩展的点 BeanPostProcessor,我们称为 Bean 后处理。跟上面的 Bean 工厂后处理器相似,它也是一个接口,实现了该接口并被容器管理的 BeanPostProcessor,会在流程节点上被 Spring 自动调用。

java 复制代码
//1. 自定义 MyBeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
    /* 参数: bean 是当前被实例化的 Bean , beanName 是当前 Bean 实例在容器中的名称
       返回值:当前 Bean 实例对象  */
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor 的 before 方法 ...");
        return bean;
    }
    /* 参数: bean 是当前被实例化的 Bean , beanName 是当前 Bean 实例在容器中的名称
       返回值:当前 Bean 实例对象  */
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor 的 after 方法 ...");
        return bean;
    }
}
XML 复制代码
```xml
//2. 注入配置 MyBeanPostProcessor
<bean class="com.apesource.processors.MyBeanPostProcessor"></bean>
java 复制代码
//3. 测试控制台打印结果如下
User 创建了...
BeanPostProcessor 的 before 方法...
User 属性填充...
User 初始化方法执行...
BeanPostProcessor 的 after 方法...
com.apesource.pojo.User@56ac3a89

三、Spring Bean 的生命周期

Spring Bean 的生命周期是从 Bean 实例化之后,即通过反射创建出对象之后,到 Bean 成为一个完整对象,最终存储到单例池中,这个过程被称为 Spring Bean 的生命周期。Spring Bean 的生命周期大体上分为四个阶段:

  • Bean 的实例化阶段 :Spring 框架会取出 BeanDefinition 的信息进行判断当前 Bean 的范围是否是 singleton 的,是否不是延迟加载的,是否不是 FactoryBean 等,最终将一个普通的 singleton 的 Bean 通过反射进行实例化;
  • Bean 的属性填充阶段:Bean 创建之后还仅仅是个"半成品",还需要对 Bean 实例的属性进行填充
  • Bean 的初始化阶段 :此外还可能执行一些 Aware 接口方法、执行 BeanPostProcessor 方法、执行 InitializingBean 接口的初始化方法、执行自定义初始化 init 方法等。该阶段是 Spring 最具技术含量和复杂度的阶段;
  • Bean 的完成阶段 :经过初始化阶段,Bean 就成为了一个完整的 Spring Bean,被存储到单例池 singletonObjects 中去了,即完成了 Spring Bean 的整个生命周期。

由于 Bean 的初始化阶段的步骤比较复杂,所以着重研究 Bean 的初始化阶段。

3.1 Spring Bean 的初始化过程

Spring Bean 的初始化过程涉及如下几个过程:

  1. Bean 实例的属性填充
  2. Aware 接口属性注入
  3. BeanPostProcessor 的 before() 方法回调
  4. InitializingBean 接口的初始化方法回调
  5. 自定义初始化方法 init 回调
  6. BeanPostProcessor 的 after() 方法回调

3.2 Bean 实例属性填充

BeanDefinition 中有对当前 Bean 实体的注入信息通过属性 propertyValues 进行了存储。

总结: Spring 在进行属性注入时,会分为如下几种情况:

  • 注入普通属性,String、int 或存储基本类型的集合时,直接通过 set 方法的反射设置进去;
  • 注入单向对象引用属性时,从容器中 getBean 获取后通过 set 方法反射设置进去,如果容器中没有,则先创建被注入对象 Bean 实例(完成整个生命周期)后,在进行注入操作;
  • 注入双向对象引用属性时,就比较复杂了,涉及了循环引用(循环依赖)。

3.3 注入单向对象引用属性演示

3.4 注入双向对象引用属性演示

含义:多个实体之间相互依赖并形成闭环的情况就叫做"循环依赖",也叫做"循环引用"。

3.5 常用的 Aware 接口

Aware 接口是一种框架辅助属性注入的一种思想,其他框架中也可以看到类似的接口。框架具备高度封装性,我们接触到的一般都是业务代码,一个底层功能 API 不能轻易的获取到,但是这不意味着永远用不到这些对象,如果用到了,就可以使用框架提供的类似 Aware 的接口,让框架给我们注入该对象。

总结:处理器的作用,为 Bean 生命周期各个阶段提供扩展

Aware 接口 回调方法 作用
ServletContextAware setServletContext(ServletContext context) Spring 框架回调方法注入 ServletContext 对象,web 环境下才生效
BeanFactoryAware setBeanFactory(BeanFactory factory) Spring 框架回调方法注入 beanFactory 对象
BeanNameAware setBeanName(String beanName) Spring 框架回调方法注入当前 Bean 在容器中的 beanName
ApplicationContextAware setApplicationContext(ApplicationContext applicationContext) Spring 框架回调方法注入 applicationContext 对象

四、一句话简单总结

其实核心一句话:Bean 生命周期,就是 Spring 从准备创建这个对象,到对象能用,最后程序关闭把对象干掉的全过程。

相关推荐
Wang's Blog1 小时前
Java 项目实战: 交友项目:登录链路回顾与今日任务地图
java·开发语言·状态模式·交友
信誓旦旦的程序猿2 小时前
【Python量化实战宝典 #08】可转债与债券接口手册:转股价·溢价率·纯债价值(Python 可跑)
java·python·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
砚底藏山河2 小时前
python量化:行情数据回溯
java·开发语言·python·金融·maven
Jlzn88882 小时前
华东电芯分选通道数怎么配才不堵线
java·人工智能·架构·自动化·制造
流烟默2 小时前
MCP第 5 篇:用 Spring AI 写 MCP:注解、自动配置、ChatClient 集成
人工智能·spring·mcp封装
香吧香2 小时前
GRPC连接机制---长连接分析
java·网络与传输协议
CCblandy2 小时前
雪花 ID 四个边界实测:时钟回拨重号 500 个,前端 JSON.parse 直接丢精度
后端·python·算法·性能优化·架构
我是人✓3 小时前
SpringBoot项目的五种创建方式
java·spring boot·后端
Wang's Blog3 小时前
Java 项目实战: 交友项目 - 阿里云 OSS 入门案例:从创建 Bucket 到上传拿到可访问 URL
java·阿里云·交友