首页 > 作文

深入了解Spring的Bean生命周期

更新时间:2023-04-04 11:13:48 阅读: 评论:0

目录
源码下载什么是 spring bean 的生命周期bean的生命周期spring角度查看bean的定义与注册springboot角度查看bean定义和注册实例化,依赖注入,初始化bean的生命周期的扩展点bean级别容器级别常用接口instantiationawarebeanpostprocessorbeannameawarebeanfactoryawareapplicationcontextawarebeanpostprocessorinitializingbeandisposablebean常用注解@bean(initmethod = “initmethod”, destroymethod = “destroymethod”)@postconstruct@predestroy案例分析声明一个beananimal实现类我的服务类后置处理器工厂后置处理器输出结果和结果解读bean生命周期图

源码下载

本章节源码github

什么是 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.依赖注入:属性赋值调用tter方法,即是依赖注入(di)5.初始化: 初始化是用户能自定义扩展的阶段6.销毁: 销毁是用户能自定义扩展的阶段

注:其他都是在这阶段前后的扩展点

spring角度查看bean的定义与注册

refresh()

public void refresh() throws beanxception, 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 (beanxception 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.retcommoncaches();            contextrefresh.end();        }    }}

springboot角度查看bean定义和注册

1. 自动加载配置类

2. bean定义和注册

注:springboot只是比spring多了自动配置相关流程,在spring上做了一层逻辑封装。

实例化,依赖注入,初始化

abstractautowirecapablebeanfactory为autowirecapablebeanfactory接口的一个实现类,其中abstractautowirecapablebeanfactory实现类的一个方法docreatebean()

//位置:abstractautowirecapablebeanfactory#docreatebeanprotected 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 expodobject = bean;    try {    // 依赖注入,属性赋值阶段        this.populatebean(beanname, mbd, instancewrapper);        // 初始化阶段        expodobject = this.initializebean(beanname, expodobject, mbd);    } catch (throwable var18) {        ...    }    ...}

可以发现,分别调用三种方法:

createbeaninstance() -> 实例化populatebean() -> 依赖注入initializebean() -> 初始化

销毁

销毁阶段是在容器关闭时调用的,在configurableapplicationcontext#clo()

至于xxxaware,beanpostprocessor,beanfactorypostprocessor等类,只不过是对主流程的一系列扩展点而已。

bean的生命周期的扩展点

spring bean 的生命周期的扩展点很多,这里不可能全部列出来,只说核心的扩展点。这也就是为什铬离子么 spring 的扩展性很好的原因,开了很多的口子,尽可能让某个功能高内聚松耦合,用户需要哪个功能就用哪个,而不是直接来一个大而全的东西。

bean级别

这些接口的实现类是基于 bean 的,只要实现了这些接口的bean才起作用。

beannameawarebeanfactoryawareapplicationcontextawareinitializingbeandisposablebean

还要很多的xxxaware,这些不常用,下面生命周期测试就不加上,如:

beanclassloaderawareenvironmentawareembeddedvalueresolverawareresourceloaderawareapplicationeventpublisherawaremessagesourceawarervletcontextaware

容器级别

这些接口的实现类是独立于 bean 的,并且会注册到 spring 容器中。一般称它们的实现类为后置处理器。

在 spring 容器创建任何 bean 的时候,这些后置处理器都会发生作用

beanpostprocessor

instantiationawarebeanpostprocessor(instantiationawarebeanpostprocessor 是继承了 beanpostprocessor)

工厂后处理器接口也是容器级的。在应用上下文装配配置文件之后立即调用:

aspectjweavingenablerconfigurationclasspostprocessorcustomautowireconfigurer

常用接口

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能够感知到,只有一个方法tbeanname(string name),获取到自身在spring容器中的id或name属性。

beanfactoryaware

该接口只有一个方法tbeanfactory(beanfactory beanfactory),用来获取当前环境中的 beanfactory,可以对工厂中的所有bean进行扩展。

applicationcontextaware

该接口只有一个方法tapplicationcontext(applicationcontext applicationcontext),用来获取当前环境中的 applicationcontext,可以对整个容器进行扩展。

注:有时候并不会调用该接口,这要根据你的ioc容器来决定:spring ioc容器最低要求是实现beanfactory接口,而不是实现applicationcontext接口,对于那些没有实现applicationcontext接口的容器,在生命周期对应的app侦查学是干什么的licationcontextaware定义的方法也是不会调用的,只要实现了applicationcontext接口的容器,才会调用。

beanpostprocessor

postprocessbeforeinitialization(object bean, string beanname):在初始化之前调用此方法,spring 的 aop 就是利用它实现的。

postprocessafterinitialization(object bean, string beanname):在初始化之后调用此方法

initializingbean

该接口只有一个方法afterpropertiest(),在属性注入完成后调用。

凡是继承该接口的类,在初始化bean的时候都会执行该方法,可以进行一些属性配置等工作。

initializingbean 对应生命周期的初始化阶段,在源码的invokeinitmethods(beanname, wrappedbean, mbd)方法中调用。

disposablebean

该接口的作用是在对象销毁时调用,可以做一些资源销毁操作。

disposablebean 类似于initializingbean,对应生命周期的销毁阶段,以configurableapplicationcontext#clo()方法作为入口,实现是通过循环取所有实现了disposablebean接口的bean然后调用其destroy()方法

常用注解

@bean(initmethod = “initmethod”, destroymethod = “destroymethod”)

@bean声明一个bean,配合@configuration注解使用

initmethod:声明bean初始化时回调一个方法,该方法需要程序员编写

destroymethod:声明bean销毁时回调一个方法,该方法需要程序员编写

@postconstruct

bean的一个基于注解的初始化方法

@predestroy

bean的一个基于注解的销毁方法

案例分析

声明一个bean

@configurationpublic class beaninitanddestroyconfig {    /**     * @return 这里没有指定bean名字,默认是方法名     */    @description("测试bean的生命周期")    @bean(initmethod = "initmethod", destroymethod = "destroymethod")    public myrvice myrvicebeanname() {//入参数可注入其他依赖        return new myrvice();    }}
声明一个名为:myrvicebeanname的beaninitmethod:bean的初始化方法为:initmethoddestroymethod:bean的销毁方法为:destroymethod

animal实现类

这里只是想用来说明 @qualifier注解能根据bean名称匹配。

我的服务类

即是针对当前bean只调用一次的接口

/** * @description: bean生命周期测试:这些接口只针对当前bean * @author: jianweil * @date: 2021/12/8 9:46 */public class myrvice implements person, beannameaware, beanfactoryaware, applicationcontextaware, initializingbean, disposablebean {    private animal animal = null;    private applicationcontext applicationcontext;    /**     *接口规定方法     */    @override    public void rvice() {        this.animal.u();    }    public myrvice() {        system.out.println("2. [bean实例化]:"+this.getclass().getsimplename()+"----------构造方法");    }    /**     *接口规定方法:注入依赖     */    @override    @autow小女生化妆ired    @qualifier("dog")    public void tanimal(animal animal) {        system.out.println("5. [bean属性赋值]:dog----依赖注入");        this.animal = animal;    }    @override    public void tbeanname(string s) {        system.out.println("6. 调用【beannameaware】--tbeanname:"+s);    }    @override    public void tbeanfactory(beanfactory beanfactory) throws beanxception {        system.out.println("7. 调用【beanfactoryaware】--tbeanfactory");    }    @override    public void tapplicationcontext(applicationcontext applicationcontext) throws beanxception {        this.applicationcontext = applicationcontext;        system.out.println("8. 调用【applicationcontextaware】--tapplicationcontext");    }    /**     * 初始化1     */    @postconstruct    public void myinit() {        system.out.println("10. [初始化] 注解@postconstruct自定义初始化方法[myinit]");    }    /**     * 初始化2     */    @override    public void afterpropertiest() throws exception {        system.out.println("11. [初始化] 接口initializingbean方法[afterpropertiest]");    }    /**     * 初始化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 */@componentpublic class myinstantiationawarebeanpostprocessor implements instantiationawarebeanpostprocessor {    @override    public ob四川高考报名网ject postprocessbeforeinstantiation(class<?> beanclass, string beanname) thr池方圆ows beanxception {        if ("myrvicebeanname".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 beanxception {        if ("myrvicebeanname".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 beanxception {        if ("myrvicebeanname".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 */@componentpublic class mybeanpostprocessor implements beanpostprocessor {    @override    public object postprocessbeforeinitialization(object bean, string beanname) throws beanxception {        //这里过滤掉springboot自动配置的bean,只打印我们项目的bean情况        if ("myrvicebeanname".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 beanxception {        if ("myrvicebeanname".equals(beanname) || "dog".equals(beanname)) {            system.out.println("13. [容器级别每个bean都回调] 调用 beanpostprocessor.postprocessafterinitialization 方法:beanname为" + beanname);        }        return bean;    }}

工厂后置处理器

容器级别,只允许一次

@componentpublic class mybeanfactorypostprocessor implements beanfactorypostprocessor {    @override    public void postprocessbeanfactory(configurablelistablebeanfactory beanfactory) throws beanxception {        system.out.println("0. [容器级别只调用一次] 调用 beanfactorypostprocessor.postprocessbeanfactory() 方法");    }}

输出结果和结果解读

“//”标记为解读

//容器级别的工厂后置处理器,只在应用上下文装配配置文件之后立即调用1次0. [容器级别只调用一次] 调用 beanfactorypostprocessor.postprocessbeanfactory() 方法//因为我们生命过程只打印("myrvicebeanname".equals(beanname) || "dog".equals(beanname)),所有猫只有构造方法打印了猫----------构造方法//###############################dog的生命周期###############################################//后置处理器,容器级别,作用于所有bean============================instantiationawarebeanpostprocessor-开始======================1. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessbeforeinstantiation() 方法:beanname为dog//狗的实例化狗----------构造方法//后置处理器,容器级别,作用于所有bean3. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessafterinstantiation() 方法:beanname为dog//后置处理器,容器级别,作用于所有bean4. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessproperties() 方法:beanname为dog============================instantiationawarebeanpostprocessor-结束======================//后置处理器,容器级别,作用于所有bean9. [容器级别每个bean都回调] 调用 beanpostprocessor.postprocessbeforeinitialization 方法:beanname为dog//后置处理器,容器级别,作用于所有bean13. [容器级别每个bean都回调] 调用 beanpostprocessor.postprocessafterinitialization 方法:beanname为dog//###############################dog的bean完成,开始myrvicebeanname###############################################//后置处理器,容器级别,作用于所有bean============================instantiationawarebeanpostprocessor-开始======================1. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessbeforeinstantiation() 方法:beanname为myrvicebeanname//实例化2. [bean实例化]:myrvice----------构造方法//后置处理器,容器级别,作用于所有bean3. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessafterinstantiation() 方法:beanname为myrvicebeanname//后置处理器,容器级别,作用于所有bean4. [容器级别每个bean都回调] 调用 instantiationawarebeanpostprocessor.postprocessproperties() 方法:beanname为myrvicebeanname============================instantiationawarebeanpostprocessor-结束======================//属性赋值,即是依赖注入5. [bean属性赋值]:dog----依赖注入//bean级别,bean:myrvicebeanname实现了接口beannameaware6. 调用【beannameaware】--tbeanname:myrvicebeanname//bean级别7. 调用【beanfactoryaware】--tbeanfactory//bean级别8. 调用【applicationcontextaware】--tapplicationcontext//后置处理器,容器级别,作用于所有bean:初始化前处理9. [容器级别每个bean都回调] 调用 beanpostprocessor.postprocessbeforeinitialization 方法:beanname为myrvicebeanname//初始化10. [初始化] 注解@postconstruct自定义初始化方法[myinit]11. [初始化] 接口initializingbean方法[afterpropertiest]12. [初始化] 注解@bean自定义初始化方法[initmethod]//后置处理器,容器级别,作用于所有bean:初始化后处理13. [容器级别每个bean都回调] 调用 beanpostprocessor.postprocessafterinitialization 方法:beanname为myrvicebeanname//容器环境加载完成,这时可以使用所有bean2021-12-21 11:18:42.994  info 18956 --- [           main] c.l.s.springbootbeanlifecycleapplication : started springbootbeanlifecycleapplication in 0.719 conds (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生命周期的资料请关注www.887551.com其它相关文章!

本文发布于:2023-04-04 11:13:46,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/8b3803af3154ce235b97c240dd305619.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:深入了解Spring的Bean生命周期.doc

本文 PDF 下载地址:深入了解Spring的Bean生命周期.pdf

标签:方法   容器   初始化   级别
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图