深入了解Spring的Bean生命周期
源码下载
什么是 spring bean 的生命周期
对于普通的 java 对象,当 new 的时候创建对象,然后该对象就能够使用了。一旦该对象不再被使用,则由 java 自动进行垃圾回收。
而 spring 中的对象是 bean,bean 和普通的 java 对象没啥大的区别,只不过 spring 不再自己去 new 对象了,而是由 ioc 容器去帮助我们实例化对象并且管理它,我们需要哪个对象,去问 ioc 容器要即可。ioc 其实就是解决对象之间的耦合问题,spring bean 的生命周期完全由容器控制。
bean的生命周期
spring bean的生命周期阶段是:
- 1.
bean定义
:就是从xml或注解定位资源加载读取bean的元信息并定义成一个beandefinition对象 - 2.
bean注册
:将beandefinition对象根据相应的规则放到缓存池map中 - 3.
实例化
:根据beandefinition实例化真正的bean,即是调用构造函数 - 4.
依赖注入
:属性赋值调用setter方法,即是依赖注入(di) - 5.
初始化
: 初始化是用户能自定义扩展的阶段 - 6.
销毁
: 销毁是用户能自定义扩展的阶段
注:其他都是在这阶段前后的扩展点
spring角度查看bean的定义与注册
refresh()
public void refresh() throws beansexception, illegalstateexception { synchronized(this.startupshutdownmonitor) { startupstep contextrefresh = this.applicationstartup.start("spring.context.refresh"); // 准备bean初始化相关的环境信息,其内部提供了一个空实现的initpropertysources()方法用于提供给用户一个更改相关环境信息的机会 this.preparerefresh(); // 创建beanfactory实例,并且注册相关的bean信息 configurablelistablebeanfactory beanfactory = this.obtainfreshbeanfactory(); // 注册aware和processor实例,并且注册了后续处理请求所需的一些editor信息 this.preparebeanfactory(beanfactory); try { // 提供的一个空方法,用于供给子类对已经生成的beanfactory的一些信息进行定制 this.postprocessbeanfactory(beanfactory); startupstep beanpostprocess = this.applicationstartup.start("spring.context.beans.post-process"); // 调用beanfactorypostprocessor及其子接口的相关方法,这些接口提供了一个入口,提供给了调用方一个修改已经生成的beandefinition的入口 this.invokebeanfactorypostprocessors(beanfactory); // 对beanpostprocessor进行注册 this.registerbeanpostprocessors(beanfactory); beanpostprocess.end(); // 初始化国际化所需的bean信息 this.initmessagesource(); // 初始化事件广播器的bean信息 this.initapplicationeventmulticaster(); // 提供的一个空方法,供给子类用于提供自定义的bean信息,或者修改已有的bean信息 this.onrefresh(); // 注册事件监听器 this.registerlisteners(); // 对已经注册的非延迟(配置文件指定)bean的实例化 this.finishbeanfactoryinitialization(beanfactory); // 清除缓存的资源信息,初始化一些声明周期相关的bean,并且发布context已被初始化的事件 this.finishrefresh(); } catch (beansexception var10) { if (this.logger.iswarnenabled()) { this.logger.warn("exception encountered during context initialization - cancelling refresh attempt: " + var10); } // 发生异常则销毁已经生成的bean this.destroybeans(); // 重置refresh字段信息 this.cancelrefresh(var10); throw var10; } finally { // 初始化一些缓存信息 this.resetcommoncaches(); contextrefresh.end(); } } }
springboot角度查看bean定义和注册
1. 自动加载配置类
2. bean定义和注册
注:springboot只是比spring多了自动配置相关流程,在spring上做了一层逻辑封装。
实例化,依赖注入,初始化
abstractautowirecapablebeanfactory为autowirecapablebeanfactory接口的一个实现类,其中abstractautowirecapablebeanfactory实现类的一个方法docreatebean()
//位置:abstractautowirecapablebeanfactory#docreatebean protected object docreatebean(string beanname, rootbeandefinition mbd, @nullable object[] args) throws beancreationexception { beanwrapper instancewrapper = null; if (mbd.issingleton()) { instancewrapper = (beanwrapper)this.factorybeaninstancecache.remove(beanname); } if (instancewrapper == null) { // 实例化阶段 instancewrapper = this.createbeaninstance(beanname, mbd, args); } ... object exposedobject = bean; try { // 依赖注入,属性赋值阶段 this.populatebean(beanname, mbd, instancewrapper); // 初始化阶段 exposedobject = this.initializebean(beanname, exposedobject, mbd); } catch (throwable var18) { ... } ... }
可以发现,分别调用三种方法:
- createbeaninstance() -> 实例化
- populatebean() -> 依赖注入
- initializebean() -> 初始化
销毁
销毁阶段是在容器关闭时调用的,在configurableapplicationcontext#close()
至于xxxaware,beanpostprocessor,beanfactorypostprocessor等类,只不过是对主流程的一系列扩展点而已。
bean的生命周期的扩展点
spring bean 的生命周期的扩展点很多,这里不可能全部列出来,只说核心的扩展点。这也就是为什么 spring 的扩展性很好的原因,开了很多的口子,尽可能让某个功能高内聚松耦合,用户需要哪个功能就用哪个,而不是直接来一个大而全的东西。
bean级别
这些接口的实现类是基于 bean 的,只要实现了这些接口的bean才起作用。
- beannameaware
- beanfactoryaware
- applicationcontextaware
- initializingbean
- disposablebean
还要很多的xxxaware,这些不常用,下面生命周期测试就不加上,如:
- beanclassloaderaware
- environmentaware
- embeddedvalueresolveraware
- resourceloaderaware
- applicationeventpublisheraware
- messagesourceaware
- servletcontextaware
容器级别
这些接口的实现类是独立于 bean 的,并且会注册到 spring 容器中。一般称它们的实现类为后置处理器。
在 spring 容器创建任何 bean 的时候,这些后置处理器都会发生作用
beanpostprocessor
instantiationawarebeanpostprocessor(instantiationawarebeanpostprocessor 是继承了 beanpostprocessor)
工厂后处理器接口也是容器级的。在应用上下文装配配置文件之后立即调用:
- aspectjweavingenabler
- configurationclasspostprocessor
- customautowireconfigurer
常用接口
instantiationawarebeanpostprocessor
该类是 beanpostprocessor 的子接口,常用的有如下三个方法:
- postprocessbeforeinstantiation(class beanclass, string beanname):在bean实例化之前调用
- postprocessproperties(propertyvalues pvs, object bean, string beanname):在bean实例化之后、设置属性前调用
- postprocessafterinstantiation(class beanclass, string beanname):在bean实例化之后调用
beannameaware
beannameaware接口是为了让自身bean能够感知到,只有一个方法setbeanname(string name),获取到自身在spring容器中的id或name属性。
beanfactoryaware
该接口只有一个方法setbeanfactory(beanfactory beanfactory),用来获取当前环境中的 beanfactory,可以对工厂中的所有bean进行扩展。
applicationcontextaware
该接口只有一个方法setapplicationcontext(applicationcontext applicationcontext),用来获取当前环境中的 applicationcontext,可以对整个容器进行扩展。
注:有时候并不会调用该接口,这要根据你的ioc容器来决定:spring ioc容器最低要求是实现beanfactory接口,而不是实现applicationcontext接口,对于那些没有实现applicationcontext接口的容器,在生命周期对应的applicationcontextaware定义的方法也是不会调用的,只要实现了applicationcontext接口的容器,才会调用。
beanpostprocessor
postprocessbeforeinitialization(object bean, string beanname):在初始化之前调用此方法,spring 的 aop 就是利用它实现的。
postprocessafterinitialization(object bean, string beanname):在初始化之后调用此方法
initializingbean
该接口只有一个方法afterpropertiesset(),在属性注入完成后调用。
凡是继承该接口的类,在初始化bean的时候都会执行该方法,可以进行一些属性配置等工作。
initializingbean 对应生命周期的初始化阶段,在源码的invokeinitmethods(beanname, wrappedbean, mbd)方法中调用。
disposablebean
该接口的作用是在对象销毁时调用,可以做一些资源销毁操作。
disposablebean 类似于initializingbean,对应生命周期的销毁阶段,以configurableapplicationcontext#close()方法作为入口,实现是通过循环取所有实现了disposablebean接口的bean然后调用其destroy()方法
常用注解
@bean(initmethod = "initmethod", destroymethod = "destroymethod")
@bean声明一个bean,配合@configuration注解使用
initmethod:声明bean初始化时回调一个方法,该方法需要程序员编写
destroymethod:声明bean销毁时回调一个方法,该方法需要程序员编写
@postconstruct
bean的一个基于注解的初始化方法
@predestroy
bean的一个基于注解的销毁方法
案例分析
声明一个bean
@configuration public class beaninitanddestroyconfig { /** * @return 这里没有指定bean名字,默认是方法名 */ @description("测试bean的生命周期") @bean(initmethod = "initmethod", destroymethod = "destroymethod") public myservice myservicebeanname() {//入参数可注入其他依赖 return new myservice(); } }
- 声明一个名为:myservicebeanname的bean
- initmethod:bean的初始化方法为:initmethod
- destroymethod:bean的销毁方法为:destroymethod
animal实现类
这里只是想用来说明 @qualifier注解能根据bean名称匹配。
我的服务类
即是针对当前bean只调用一次的接口
/** * @description: bean生命周期测试:这些接口只针对当前bean * @author: jianweil * @date: 2021/12/8 9:46 */ public class myservice implements person, beannameaware, beanfactoryaware, applicationcontextaware, initializingbean, disposablebean { private animal animal = null; private applicationcontext applicationcontext; /** *接口规定方法 */ @override public void service() { this.animal.use(); } public myservice() { system.out.println("2. [bean实例化]:"+this.getclass().getsimplename()+"----------构造方法"); } /** *接口规定方法:注入依赖 */ @override @autowired @qualifier("dog") public void setanimal(animal animal) { system.out.println("5. [bean属性赋值]:dog----依赖注入"); this.animal = animal; } @override public void setbeanname(string s) { system.out.println("6. 调用【beannameaware】--setbeanname:"+s); } @override public void setbeanfactory(beanfactory beanfactory) throws beansexception { system.out.println("7. 调用【beanfactoryaware】--setbeanfactory"); } @override public void setapplicationcontext(applicationcontext applicationcontext) throws beansexception { this.applicationcontext = applicationcontext; system.out.println("8. 调用【applicationcontextaware】--setapplicationcontext"); } /** * 初始化1 */ @postconstruct public void myinit() { system.out.println("10. [初始化] 注解@postconstruct自定义初始化方法[myinit]"); } /** * 初始化2 */ @override public void afterpropertiesset() throws exception { system.out.println("11. [初始化] 接口initializingbean方法[afterpropertiesset]"); } /** * 初始化3 */ public void initmethod() { system.out.println("12. [初始化] 注解@bean自定义初始化方法[initmethod]"); } /** * 销毁1 */ @predestroy public void mydestroy() { system.out.println("14. [销毁] 注解@predestroy自定义销毁方法[mydestroy]"); } /** * 销毁2 */ @override public void destroy() throws exception { system.out.println("15. [销毁] 接口disposablebean方法[destroy]"); } /** * 销毁3 */ public void destroymethod() { system.out.println("16. [销毁] 注解@bean自定义销毁方法[destroymethod]"); } }
这里实现的接口只作用于当前bean(即是上面@bean定义的bean名为mydefinebeanname)生命周期
后置处理器
每个bean生命周期都执行一次
后置处理器是作用于ioc容器中所有bean的生命周期。
/** * @description: todo * @author: jianweil * @date: 2021/12/20 17:20 */ @component public class myinstantiationawarebeanpostprocessor implements instantiationawarebeanpostprocessor { @override public object postprocessbeforeinstantiation(class<?> beanclass, string beanname) throws beansexception { if ("myservicebeanname".equals(beanname) || "dog".equals(beanname)) { system.out.println("============================instantiationawarebeanpostprocessor-开始======================"); system.out.println("1. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessbeforeinstantiation() 方法:beanname为"+beanname); } return null; } @override public boolean postprocessafterinstantiation(object bean, string beanname) throws beansexception { if ("myservicebeanname".equals(beanname) || "dog".equals(beanname)) { system.out.println("3. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessafterinstantiation() 方法:beanname为"+beanname); } return true; } @override public propertyvalues postprocessproperties(propertyvalues pvs, object bean, string beanname) throws beansexception { if ("myservicebeanname".equals(beanname) || "dog".equals(beanname)) { system.out.println("4. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessproperties() 方法:beanname为"+beanname); system.out.println("============================instantiationawarebeanpostprocessor-结束======================"); } return null; } }
/** * @description: 后置bean的初始化器:所有的bean都会拦截执行 * @author: jianweil * @date: 2021/12/8 9:46 */ @component public class mybeanpostprocessor implements beanpostprocessor { @override public object postprocessbeforeinitialization(object bean, string beanname) throws beansexception { //这里过滤掉springboot自动配置的bean,只打印我们项目的bean情况 if ("myservicebeanname".equals(beanname) || "dog".equals(beanname)) { system.out.println("9. [容器级别每个bean都回调] 调用 beanpostprocessor.postprocessbeforeinitialization 方法:beanname为" + beanname); } return bean; } @override public object postprocessafterinitialization(object bean, string beanname) throws beansexception { if ("myservicebeanname".equals(beanname) || "dog".equals(beanname)) { system.out.println("13. [容器级别每个bean都回调] 调用 beanpostprocessor.postprocessafterinitialization 方法:beanname为" + beanname); } return bean; } }
工厂后置处理器
容器级别,只允许一次
@component public class mybeanfactorypostprocessor implements beanfactorypostprocessor { @override public void postprocessbeanfactory(configurablelistablebeanfactory beanfactory) throws beansexception { system.out.println("0. [容器级别只调用一次] 调用 beanfactorypostprocessor.postprocessbeanfactory() 方法"); } }
输出结果和结果解读
“//”标记为解读
//容器级别的工厂后置处理器,只在应用上下文装配配置文件之后立即调用1次 0. [容器级别只调用一次] 调用 beanfactorypostprocessor.postprocessbeanfactory() 方法 //因为我们生命过程只打印("myservicebeanname".equals(beanname) || "dog".equals(beanname)),所有猫只有构造方法打印了 猫----------构造方法 //###############################dog的生命周期############################################### //后置处理器,容器级别,作用于所有bean ============================instantiationawarebeanpostprocessor-开始====================== 1. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessbeforeinstantiation() 方法:beanname为dog //狗的实例化 狗----------构造方法 //后置处理器,容器级别,作用于所有bean 3. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessafterinstantiation() 方法:beanname为dog //后置处理器,容器级别,作用于所有bean 4. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessproperties() 方法:beanname为dog ============================instantiationawarebeanpostprocessor-结束====================== //后置处理器,容器级别,作用于所有bean 9. [容器级别每个bean都回调] 调用 beanpostprocessor.postprocessbeforeinitialization 方法:beanname为dog //后置处理器,容器级别,作用于所有bean 13. [容器级别每个bean都回调] 调用 beanpostprocessor.postprocessafterinitialization 方法:beanname为dog //###############################dog的bean完成,开始myservicebeanname############################################### //后置处理器,容器级别,作用于所有bean ============================instantiationawarebeanpostprocessor-开始====================== 1. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessbeforeinstantiation() 方法:beanname为myservicebeanname //实例化 2. [bean实例化]:myservice----------构造方法 //后置处理器,容器级别,作用于所有bean 3. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessafterinstantiation() 方法:beanname为myservicebeanname //后置处理器,容器级别,作用于所有bean 4. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessproperties() 方法:beanname为myservicebeanname ============================instantiationawarebeanpostprocessor-结束====================== //属性赋值,即是依赖注入 5. [bean属性赋值]:dog----依赖注入 //bean级别,bean:myservicebeanname实现了接口beannameaware 6. 调用【beannameaware】--setbeanname:myservicebeanname //bean级别 7. 调用【beanfactoryaware】--setbeanfactory //bean级别 8. 调用【applicationcontextaware】--setapplicationcontext //后置处理器,容器级别,作用于所有bean:初始化前处理 9. [容器级别每个bean都回调] 调用 beanpostprocessor.postprocessbeforeinitialization 方法:beanname为myservicebeanname //初始化 10. [初始化] 注解@postconstruct自定义初始化方法[myinit] 11. [初始化] 接口initializingbean方法[afterpropertiesset] 12. [初始化] 注解@bean自定义初始化方法[initmethod] //后置处理器,容器级别,作用于所有bean:初始化后处理 13. [容器级别每个bean都回调] 调用 beanpostprocessor.postprocessafterinitialization 方法:beanname为myservicebeanname //容器环境加载完成,这时可以使用所有bean 2021-12-21 11:18:42.994 info 18956 --- [ main] c.l.s.springbootbeanlifecycleapplication : started springbootbeanlifecycleapplication in 0.719 seconds (jvm running for 1.312) //销毁 14. [销毁] 注解@predestroy自定义销毁方法[mydestroy] 15. [销毁] 接口disposablebean方法[destroy] 16. [销毁] 注解@bean自定义销毁方法[destroymethod] process finished with exit code 0
bean生命周期图
了解 spring 生命周期的意义就在于,可以利用 bean 在其存活期间的指定时刻完成一些相关操作。一般情况下,会在 bean 被初始化后和被销毁前执行一些相关操作。
以上就是深入了解spring的bean生命周期的详细内容,更多关于spring bean生命周期的资料请关注其它相关文章!
推荐阅读