Spring Bean的初始化过程

今天我们总结一下Spring Bean在初始化过程中执行了哪些方法,他们的先后顺序是怎么样的。

spring容器中一个bean的初始化过程,大体上都会经历下面八个阶段,且按序号标识依次执行:

  • BeanFactoryPostProcessor.postProcessBeanFactory

  • BeanPostProcessor.postProcessBeforeInitialization

  • 构造函数

  • set属性(@Autowired)

  • @PostConstruct

  • InitializeBean.afterPropertiesSet

  • initMethod()

  • BeanPostProcessor.postProcessAfterInitialization

BeanFactoryPostProcessor.postProcessBeanFactory

BeanFactoryPostProcessor 允许自定义修改应用程序上下文的bean定义,调整上下文的底层bean工厂的bean属性值;应用程序上下文可以在bean定义中自动检测BeanFactoryPostProcessor bean,并在创建任何其他bean之前应用它们。BeanFactoryPostProcessor仅能用来修改bean的定义,但是不可以用来实例化bean,因为这样会造成bean被过早的实例化,违反容器的规则,导致意想不到的后果。

postProcessBeanFactory可以在spring的bean初始化之前,来修改bean的定义及属性。也就是说, Spring允许BeanFactoryPostProcessor在容器实例化任何bean之前读取配置信息,并根据需求进行修改,例如修改bean的scope,修改property的值等等;

可以配置多个BeanFactoryPostProcessor, 并通过设置order属性来控制BeanFactoryPostProcessor的执行次序。

BeanPostProcessor.postProcessBeforeInitialization

BeanPostProcessor是一个允许自定义修改bean实例的钩子,可以在bean初始化方法的前、后,添加一些自己的处理逻辑;这里说的初始化方法,包括两个:一个是InitializingBean接口的afterPropertiesSet方法,以及在bean定义的时候通过init-method设置的方法。它的执行时在BeanFactoryPostProcessor之后。

postProcessBeforeInitialization的运行时在bean初始化方法之前,而postProcessAfterInitialization的运行时在bean初始化方法之后。

构造函数

经过BeanFactoryPostProcessor对bean的相关配置进行修改后,就来到了bean的构造函数。如果没有自定义的构造函数,则会调用默认的无参构造函数。

set属性(@Autowired)

将bean通过构造函数被初始化后,紧接着就会执行依赖注入,赋值bean的属性

@PostConstruct

在bean的属性被注入完成后,且bean被使用之前,PostConstruct会被调用,且仅调用一次。

InitializeBean.afterPropertiesSet

实现了该接口的bean, 需要在BeanFactory设置了所有的属性后,执行afterpropertiesSet方法。

init-method

在spring的声明式配置中,经常会配置init-method方法,init-method配置的方法,会在afterpropertiesSet之后执行。

BeanPostProcessor.postProcessAfterInitialization

与BeanPostProcessor.postProcessBeforeInitialization相同,

只不过postProcessAfterInitialization会在init-method之后执行。

了解了spring bean 初始化的各种方法,以及他们执行的顺序后,我们就可以在以后的开发过程中,灵活地对bean进行操作。

总结:

因为Spring拥有很庞大的体系结构,没办法介绍的面面俱到,因此摘了部分核心代码,配合流程图讲解,基本把整个Bean的初始化乃至整个IOC容器的初始化过程,简述了出来。如果小伙伴想要更加深入的了解Spring源码,可以配合debug,走一遍IOC初始化的流程。

最后再总结下整个Bean的整个生命周期过程:

  • 1、Spring通过反射创建Bean对象 ;

  • 2、完成当前Bean的依赖注入 **(**成员变量填充);

  • 3、如果Bean有实现Aware接口,则调用各种Aware接口的方法设置属性;

  • 4、执行BeanPostProcessor 的前置方法(通常是一个集合,形成一个调用链,依次执行);

  • 5、完成开发者自定义的初始化方法(init-method 或者**@PostConstruct**注解标记的方法);

  • 6、执行BeanPostProcessor 的后置方法(通常是一个集合,形成一个调用链,依次执行);

  • 7、完成初始化,将Bean放入BeanFactory集合中(核心是一个Map集合);

  • 8、Bean对象随着BeanFactory关闭而销毁,执行开发者自定义的销毁方法 **(**destory-method或者@PreDestory注解标记的方法)。

相关推荐
蜗牛一步步往上爬16 小时前
第十六章 C++语言在深度学习中的应用
开发语言·c++·深度学习
这个昵称不容易18 小时前
SpringBoot「衣依」服装销售平台:144个Java文件180个接口,从挑衣服到收货评价整条链路都在
java·springboot·毕设
计算机毕设定制辅导-无忧学长18 小时前
《基于微信小程序的居家医疗陪护预约系统设计与实现》
java·spring boot·微信小程序·uniapp·居家医疗陪护预约系统
张张123y18 小时前
DSH 插件调试避坑:client.js 设置面板、热重载与高频报错排查表
开发语言·javascript·人工智能·开源·ecmascript·后端开发·ai agent
文丑颜不良啊19 小时前
LeetCode2221~2240题目解析
java·leetcode
秋饼19 小时前
Computer Use Agent Java 落地实战:感知-行动循环、执行器与安全围栏生产级实现
java·ai·技术分享·后端开发
冻柠檬飞冰走茶21 小时前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划
文丑颜不良啊21 小时前
LeetCode2161~2180题目解析
java·leetcode
FRing0321 小时前
vue2干货总结7(自定义指令、插槽、单页应用程序、路由的使用(VueRouter))
开发语言·前端·vue.js·vue2
雪落漂泊21 小时前
C++算法 二分查找篇(上)
开发语言·c++·算法