欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

程序员文章站 2023-10-29 10:37:04
在网上已经有跟多Bean的生命周期的博客,但是很多都是基于比较老的版本了,最近吧整个流程化成了一个流程图。待会儿使用流程图,说明以及代码的形式来说明整个声明周期的流程。注意因为代码比较多,这里的流程图只画出了大概的流程,具体的可以深入代码 一、获取Bea 第一阶段获取Bean 这里的流程图的入口在  ......

在网上已经有跟多bean的生命周期的博客,但是很多都是基于比较老的版本了,最近吧整个流程化成了一个流程图。待会儿使用流程图,说明以及代码的形式来说明整个声明周期的流程。注意因为代码比较多,这里的流程图只画出了大概的流程,具体的可以深入代码

一、获取bea

 

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

第一阶段获取bean

这里的流程图的入口在 abstractbeanfactory类的 dogetbean方法,这里可以配合前面的 getbean方法分析文章进行阅读。主要流程就是

1、先处理bean 的名称,因为如果以“&”开头的bean名称表示获取的是对应的factorybean对象;
2、从缓存中获取单例bean,有则进一步判断这个bean是不是在创建中,如果是的就等待创建完毕,否则直接返回这个bean对象
3、如果不存在单例bean缓存,则先进行循环依赖的解析
4、解析完毕之后先获取父类beanfactory,获取到了则调用父类的getbean方法,不存在则先合并然后创建bean

二、创建bean

2.1 创建bean之前

 

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

在真正创建bean之前逻辑

这个流程图对应的代码在 abstractautowirecapablebeanfactory类的 createbean方法中。

1、这里会先获取 rootbeandefinition对象中的class对象并确保已经关联了要创建的bean的class 。整编:微信公众号,搜云库技术团队,id:souyunku
2、这里会检查3个条件

(1)bean的属性中的 beforeinstantiationresolved字段是否为true,默认是false。
(2)bean是原生的bean
(3)bean的 hasinstantiationawarebeanpostprocessors属性为true,这个属性在spring准备刷新容器钱转杯beanpostprocessors的时候会设置,如果当前bean实现了 instantiationawarebeanpostprocessor则这个就会是true。

当三个条件都存在的时候,就会调用实现的 instantiationawarebeanpostprocessor接口的 postprocessbeforeinstantiation方法,然后获取返回的bean,如果返回的bean不是null还会调用实现的 beanpostprocessor接口的 postprocessafterinitialization方法,这里用代码说明

protected object resolvebeforeinstantiation(string beanname, rootbeandefinition mbd) {
 object bean = null;
 //条件1
 if (!boolean.false.equals(mbd.beforeinstantiationresolved)) {
 //条件2跟条件3
 if (!mbd.issynthetic() && hasinstantiationawarebeanpostprocessors()) {
 class<?> targettype = determinetargettype(beanname, mbd);
 if (targettype != null) {
 //调用实现的postprocessbeforeinstantiation方法
                    bean = applybeanpostprocessorsbeforeinstantiation(targettype, beanname);
 if (bean != null) {
//调用实现的postprocessafterinitialization方法
                        bean = applybeanpostprocessorsafterinitialization(bean, beanname);
 }
 }
 }
 //不满足2或者3的时候就会设置为false
            mbd.beforeinstantiationresolved = (bean != null);
 }
 return bean;
 }

 

 

1、如果上面3个条件其中一个不满足就不会调用实现的方法。默认这里都不会调用的这些 beanpostprocessors的实现方法。然后继续执行后面的 docreatebean方法。

2.1 真正的创建bean,docreatebean

 

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

docreatebean方法逻辑

这个代码的实现还是在 abstractautowirecapablebeanfactory方法中。流程是

1、先检查 instancewrapper变量是不是null,这里一般是null,除非当前正在创建的bean在 factorybeaninstancecache中存在这个是保存还没创建完成的factorybean的集合。
2、调用createbeaninstance方法实例化bean,这个方法在后面会讲解
3、如果当前 rootbeandefinition对象还没有调用过实现了的 mergedbeandefinitionpostprocessor接口的方法,则会进行调用 。整编:微信公众号,搜云库技术团队,id:souyunku
4、 当满足以下三点
(1)是单例bean
(2)尝试解析bean之间的循环引用
(3)bean目前正在创建中
则会进一步检查是否实现了 smartinstantiationawarebeanpostprocessor接口如果实现了则调用是实现的 getearlybeanreference方法 5、 调用 populatebean方法进行属性填充,这里后面会讲解 6、 调用 initializebean方法对bean进行初始化,这里后面会讲解

2.1.1 实例化bean,createbeaninstance

 

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

实例化bean

这里的逻辑稍微有一点复杂,这个流程图已经是简化过后的了。简要根据代码说明一下流程

protected beanwrapper createbeaninstance(string beanname, rootbeandefinition mbd, @nullable object[] args) {
 //步骤1
 class<?> beanclass = resolvebeanclass(mbd, beanname);

 if (beanclass != null && !modifier.ispublic(beanclass.getmodifiers()) && !mbd.isnonpublicaccessallowed()) {
 throw new beancreationexception(mbd.getresourcedescription(), beanname,
 "bean class isn't public, and non-public access not allowed: " + beanclass.getname());
 }
 //步骤2
 supplier<?> instancesupplier = mbd.getinstancesupplier();
 if (instancesupplier != null) {
 return obtainfromsupplier(instancesupplier, beanname);
 }
 //步骤3
 if (mbd.getfactorymethodname() != null) {
 return instantiateusingfactorymethod(beanname, mbd, args);
 }


 boolean resolved = false;
 boolean autowirenecessary = false;
 if (args == null) {
 synchronized (mbd.constructorargumentlock) {
 if (mbd.resolvedconstructororfactorymethod != null) {
                    resolved = true;
                    autowirenecessary = mbd.constructorargumentsresolved;
 }
 }
 }
 //步骤4.1
 if (resolved) {

 if (autowirenecessary) {
 return autowireconstructor(beanname, mbd, null, null);
 }
 else {

 return instantiatebean(beanname, mbd);
 }
 }

 //步骤4.2
 constructor<?>[] ctors = determineconstructorsfrombeanpostprocessors(beanclass, beanname);
 if (ctors != null || mbd.getresolvedautowiremode() == autowire_constructor ||
                mbd.hasconstructorargumentvalues() || !objectutils.isempty(args)) {
 return autowireconstructor(beanname, mbd, ctors, args);
 }

 //步骤5
        ctors = mbd.getpreferredconstructors();
 if (ctors != null) {
 return autowireconstructor(beanname, mbd, ctors, null);
 }


 return instantiatebean(beanname, mbd);
 }

 

 

1、先检查class是否已经关联了,并且对应的修饰符是否是public的
2、如果用户定义了bean实例化的函数,则调用并返回
3、如果当前bean实现了 factorybean接口则调用对应的 factorybean接口的 getobject方法
4、根据getbean时候是否传入构造参数进行处理
4.1 如果没有传入构造参数,则检查是否存在已经缓存的无参构造器,有则使用构造器直接创建,没有就会调用 instantiatebean方法先获取实例化的策略默认是 cglibsubclassinginstantiationstrategy,然后实例化bean。最后返回
4.2 如果传入了构造参数,则会先检查是否实现了 smartinstantiationawarebeanpostprocessor接口,如果实现了会调用 determinecandidateconstructors获取返回的候选构造器。整编:微信公众号,搜云库技术团队,id:souyunku
4.3 检查4个条件是否满足一个
(1)构造器不为null,
(2)从rootbeandefinition中获取到的关联的注入方式是构造器注入(没有构造参数就是setter注入,有则是构造器注入)
(3)含有构造参数
(4)getbean方法传入构造参数不是空

满足其中一个则会调用返回的候选构造器实例化bean并返回,如果都不满足,则会根据构造参数选则合适的有参构造器然后实例化bean并返回

5、如果上面都没有合适的构造器,则直接使用无参构造器创建并返回bean。

2.1.2 填充bean,populatebean

 

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

填充bean

这里还是根据代码来说一下流程

protected void populatebean(string beanname, rootbeandefinition mbd, @nullable beanwrapper bw) {
 if (bw == null) {
 if (mbd.haspropertyvalues()) {
 throw new beancreationexception(
                        mbd.getresourcedescription(), beanname, "cannot apply property values to null instance");
 }
 else {
 // skip property population phase for null instance.
 return;
 }
 }

 

 boolean continuewithpropertypopulation = true;
 //步骤1
 if (!mbd.issynthetic() && hasinstantiationawarebeanpostprocessors()) {
 for (beanpostprocessor bp : getbeanpostprocessors()) {
 if (bp instanceof instantiationawarebeanpostprocessor) {
 instantiationawarebeanpostprocessor ibp = (instantiationawarebeanpostprocessor) bp;
 if (!ibp.postprocessafterinstantiation(bw.getwrappedinstance(), beanname)) {
                        continuewithpropertypopulation = false;
 break;
 }
 }
 }
 }

 if (!continuewithpropertypopulation) {
 return;
 }
//步骤2--------------------
 propertyvalues pvs = (mbd.haspropertyvalues() ? mbd.getpropertyvalues() : null);

 int resolvedautowiremode = mbd.getresolvedautowiremode();
 if (resolvedautowiremode == autowire_by_name || resolvedautowiremode == autowire_by_type) {
 mutablepropertyvalues newpvs = new mutablepropertyvalues(pvs);
 // add property values based on autowire by name if applicable.
 if (resolvedautowiremode == autowire_by_name) {
                autowirebyname(beanname, mbd, bw, newpvs);
 }
 // add property values based on autowire by type if applicable.
 if (resolvedautowiremode == autowire_by_type) {
                autowirebytype(beanname, mbd, bw, newpvs);
 }
            pvs = newpvs;
 }

 boolean hasinstawarebpps = hasinstantiationawarebeanpostprocessors();
 boolean needsdepcheck = (mbd.getdependencycheck() != abstractbeandefinition.dependency_check_none);

 propertydescriptor[] filteredpds = null;
//步骤3
 if (hasinstawarebpps) {
 if (pvs == null) {
                pvs = mbd.getpropertyvalues();
 }
 for (beanpostprocessor bp : getbeanpostprocessors()) {
 if (bp instanceof instantiationawarebeanpostprocessor) {
 instantiationawarebeanpostprocessor ibp = (instantiationawarebeanpostprocessor) bp;
 propertyvalues pvstouse = ibp.postprocessproperties(pvs, bw.getwrappedinstance(), beanname);
 if (pvstouse == null) {
 if (filteredpds == null) {
                            filteredpds = filterpropertydescriptorsfordependencycheck(bw, mbd.allowcaching);
 }
                        pvstouse = ibp.postprocesspropertyvalues(pvs, filteredpds, bw.getwrappedinstance(), beanname);
 if (pvstouse == null) {
 return;
 }
 }
                    pvs = pvstouse;
 }
 }
 }
 if (needsdepcheck) {
 if (filteredpds == null) {
                filteredpds = filterpropertydescriptorsfordependencycheck(bw, mbd.allowcaching);
 }
            checkdependencies(beanname, mbd, filteredpds, pvs);
 }
//步骤4
 if (pvs != null) {
            applypropertyvalues(beanname, mbd, bw, pvs);
 }
 }

 

 

1、检查当前bean是否实现了 instantiationawarebeanpostprocessor的 postprocessafterinstantiation方法则调用,并结束bean的填充。
2、将按照类型跟按照名称注入的bean分开,如果注入的bean还没有实例化的这里会实例化,然后放到 propertyvalues对象中。
3、如果实现了 instantiationawarebeanpostprocessor类的 postprocessproperties则调用这个方法并获取返回值,如果返回值是null,则有可能是实现了过期的 postprocesspropertyvalues方法,这里需要进一步调用 postprocesspropertyvalues方法
4、进行参数填充

2.1.3 初始化bean,initializebean

 

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

初始化bean

同时这里根据代码跟流程图来说明

1、如果bean实现了 beannameawarebeanclassloaderawarebeanfactoryaware则调用对应实现的方法 。整编:微信公众号,搜云库技术团队,id:souyunku
2、bean不为null并且bean不是合成的,如果实现了 beanpostprocessor的 postprocessbeforeinitialization则会调用实现的 postprocessbeforeinitialization方法。在 applicationcontextawareprocessor类中实现了 postprocessbeforeinitialization方法。而这个类会在spring刷新容器准备 beanfactory的时候会加进去,这里就会被调用,而调用里面会检查bean是不是 environmentawareembeddedvalueresolverawareresourceloaderawareapplicationeventpublisherawaremessagesourceawareapplicationcontextaware的实现类。这里就会调用对应的实现方法。代码如下

 protected void preparebeanfactory(configurablelistablebeanfactory beanfactory) {
 .......
        beanfactory.addbeanpostprocessor(new applicationcontextawareprocessor(this));
 .......

 

public object postprocessbeforeinitialization(object bean, string beanname) throws beansexception {
 if (!(bean instanceof environmentaware || bean instanceof embeddedvalueresolveraware ||
                bean instanceof resourceloaderaware || bean instanceof applicationeventpublisheraware ||
                bean instanceof messagesourceaware || bean instanceof applicationcontextaware)){
 return bean;
 }

 accesscontrolcontext acc = null;

 if (system.getsecuritymanager() != null) {
            acc = this.applicationcontext.getbeanfactory().getaccesscontrolcontext();
 }

 if (acc != null) {
 accesscontroller.doprivileged((privilegedaction<object>) () -> {
                invokeawareinterfaces(bean);
 return null;
 }, acc);
 }
 else {
            invokeawareinterfaces(bean);
 }

 return bean;
 }

 

 

1、实例化bean然后,检查是否实现了 initializingbean的 afterpropertiesset方法,如果实现了就会调用
2、bean不为null并且bean不是合成的,如果实现了 beanpostprocessor的 postprocessbeforeinitialization则会调用实现的 postprocessafterinitialization方法。

到此创建bean 的流程就没了,剩下的就是容器销毁的时候的了

三、destory方法跟销毁bean

 

bean在创建完毕之后会检查用户是否指定了 destroymethodname以及是否实现了 destructionawarebeanpostprocessor接口的 requiresdestruction方法,如果指定了会记录下来保存在 disposablebeanadapter对象中并保存在bean的 disposablebeans属性中。代码在 abstractbeanfactory的 registerdisposablebeanifnecessary

 

protected void registerdisposablebeanifnecessary(string beanname, object bean, rootbeandefinition mbd) {
 ......
                registerdisposablebean(beanname,
 new disposablebeanadapter(bean, beanname, mbd, getbeanpostprocessors(), acc));
 ......
 }

 

 

public disposablebeanadapter(object bean, string beanname, rootbeandefinition beandefinition,
 list<beanpostprocessor> postprocessors, @nullable accesscontrolcontext acc) {
 .......
 string destroymethodname = inferdestroymethodifnecessary(bean, beandefinition);
 if (destroymethodname != null && !(this.invokedisposablebean && "destroy".equals(destroymethodname)) &&
 !beandefinition.isexternallymanageddestroymethod(destroymethodname)) {
 ......
 this.destroymethod = destroymethod;
 }
 this.beanpostprocessors = filterpostprocessors(postprocessors, bean);
 }
 

 

在销毁bean的时候最后都会调用 abstractautowirecapablebeanfactory的 destroybean方法。

 public void destroybean(object existingbean) {
 new disposablebeanadapter(existingbean, getbeanpostprocessors(), getaccesscontrolcontext()).destroy();
 }

 

 

这里是创建一个 disposablebeanadapter对象,这个对象实现了runnable接口,在实现的 run方法中会调用实现的 disposablebean接口的 destroy方法。并且在创建 disposablebeanadapter对象的时候会根据传入的bean是否实现了 disposablebean接口来设置 invokedisposablebean变量,这个变量表实有没有实现 disposablebean接口

 public disposablebeanadapter(object bean, list<beanpostprocessor> postprocessors, accesscontrolcontext acc) {
 assert.notnull(bean, "disposable bean must not be null");
 this.bean = bean;
 this.beanname = bean.getclass().getname();
 //根据传入的bean是否实现了`disposablebean`接口来设置`invokedisposablebean`变量
 this.invokedisposablebean = (this.bean instanceof disposablebean);
 this.nonpublicaccessallowed = true;
 this.acc = acc;
 this.beanpostprocessors = filterpostprocessors(postprocessors, bean);
 }

 public void destroy() {
 ......
 //根据invokedisposablebean决定是否调用destroy方法
 if (this.invokedisposablebean) {
 if (logger.istraceenabled()) {
                logger.trace("invoking destroy() on bean with name '" + this.beanname + "'");
 }
 try {
 if (system.getsecuritymanager() != null) {
 accesscontroller.doprivileged((privilegedexceptionaction<object>) () -> {
 ((disposablebean) this.bean).destroy();
 return null;
 }, this.acc);
 }
 else {
 ((disposablebean) this.bean).destroy();
 }
 }
 catch (throwable ex) {
 string msg = "invocation of destroy method failed on bean with name '" + this.beanname + "'";
 if (logger.isdebugenabled()) {
                    logger.warn(msg, ex);
 }
 else {
                    logger.warn(msg + ": " + ex);
 }
 }
 }
......
 }

 

 

四、总结。

最后来一个大的流程

 

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

实例化前的准备阶段

 

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

实例化前

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

 

实例化后

 

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

初始化前

 

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

————————————————

本人免费整理了java高级资料,涵盖了java、redis、mongodb、mysql、zookeeper、spring cloud、dubbo高并发分布式等教程,一共30g,需要自己领取。
传送门:https://mp.weixin.qq.com/s/osb-bol6w-zltstttkqmpq