spring源码深度解析— IOC 之 开启 bean 的加载
概述
前面我们已经分析了spring对于xml配置文件的解析,将分析的信息组装成 beandefinition,并将其保存注册到相应的 beandefinitionregistry 中。至此,spring ioc 的初始化工作完成。接下来我们将对bean的加载进行探索。
之前系列文章:
beanfactory
当我们显示或者隐式地调用 getbean()
时,则会触发加载 bean 阶段。如下:
public class apptest { @test public void mytestbeantest() { beanfactory bf = new xmlbeanfactory( new classpathresource("spring-config.xml")); mytestbean mytestbean = (mytestbean) bf.getbean("mytestbean"); } }
我们看到这个方法是在接口beanfactory中定义的,我们看下beanfactory体系结构,如下图所示:
从上图我们看到:
(1)beanfactory作为一个主接口不继承任何接口,暂且称为一级接口。
(2)有3个子接口继承了它,进行功能上的增强。这3个子接口称为二级接口。
(3)configurablebeanfactory可以被称为三级接口,对二级接口hierarchicalbeanfactory进行了再次增强,它还继承了另一个外来的接口singletonbeanregistry
(4)configurablelistablebeanfactory是一个更强大的接口,继承了上述的所有接口,无所不包,称为四级接口。(这4级接口是beanfactory的基本接口体系。继续,下面是继承关系的2个抽象类和2个实现类:)
(5)abstractbeanfactory作为一个抽象类,实现了三级接口configurablebeanfactory大部分功能。
(6)abstractautowirecapablebeanfactory同样是抽象类,继承自abstractbeanfactory,并额外实现了二级接口autowirecapablebeanfactory
(7)defaultlistablebeanfactory继承自abstractautowirecapablebeanfactory,实现了最强大的四级接口configurablelistablebeanfactory,并实现了一个外来接口beandefinitionregistry,它并非抽象类。
(8)最后是最强大的xmlbeanfactory,继承自defaultlistablebeanfactory,重写了一些功能,使自己更强大。
定义
beanfactory,以factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂。在spring中,beanfactory是ioc容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。beanfactory只是个接口,并不是ioc容器的具体实现,但是spring容器给出了很多种实现,如 defaultlistablebeanfactory、xmlbeanfactory、applicationcontext等,其中xmlbeanfactory就是常用的一个,该实现将以xml方式描述组成应用的对象及对象间的依赖关系。xmlbeanfactory类将持有此xml配置元数据,并用它来构建一个完全可配置的系统或应用。
beanfactory是spring ioc容器的鼻祖,是ioc容器的基础接口,所有的容器都是从它这里继承实现而来。可见其地位。beanfactory提供了最基本的ioc容器的功能,即所有的容器至少需要实现的标准。
xmlbeanfactory,只是提供了最基本的ioc容器的功能。而且xmlbeanfactory,继承自defaultlistablebeanfactory。defaultlistablebeanfactory实际包含了基本ioc容器所具有的所有重要功能,是一个完整的ioc容器。
applicationcontext包含beanfactory的所有功能,通常建议比beanfactory优先。
beanfactory体系结构是典型的工厂方法模式,即什么样的工厂生产什么样的产品。beanfactory是最基本的抽象工厂,而其他的ioc容器只不过是具体的工厂,对应着各自的bean定义方法。但同时,其他容器也针对具体场景不同,进行了扩充,提供具体的服务。 如下:
resource resource = new filesystemresource("beans.xml"); beanfactory factory = new xmlbeanfactory(resource);
classpathresource resource = new classpathresource("beans.xml"); beanfactory factory = new xmlbeanfactory(resource);
applicationcontext context = new classpathxmlapplicationcontext(new string[] {"applicationcontext.xml"}); beanfactory factory = (beanfactory) context;
基本就是这些了,接着使用getbean(string beanname)方法就可以取得bean的实例;beanfactory提供的方法及其简单,仅提供了六种方法供客户调用:
- boolean containsbean(string beanname) 判断工厂中是否包含给定名称的bean定义,若有则返回true
- object getbean(string) 返回给定名称注册的bean实例。根据bean的配置情况,如果是singleton模式将返回一个共享实例,否则将返回一个新建的实例,如果没有找到指定bean,该方法可能会抛出异常
- object getbean(string, class) 返回以给定名称注册的bean实例,并转换为给定class类型
- class gettype(string name) 返回给定名称的bean的class,如果没有找到指定的bean实例,则排除nosuchbeandefinitionexception异常
- boolean issingleton(string) 判断给定名称的bean定义是否为单例模式
- string[] getaliases(string name) 返回给定bean名称的所有别名
package org.springframework.beans.factory; import org.springframework.beans.beansexception; public interface beanfactory { string factory_bean_prefix = "&"; object getbean(string name) throws beansexception; <t> t getbean(string name, class<t> requiredtype) throws beansexception; <t> t getbean(class<t> requiredtype) throws beansexception; object getbean(string name, object... args) throws beansexception; boolean containsbean(string name); boolean issingleton(string name) throws nosuchbeandefinitionexception; boolean isprototype(string name) throws nosuchbeandefinitionexception; boolean istypematch(string name, class<?> targettype) throws nosuchbeandefinitionexception; class<?> gettype(string name) throws nosuchbeandefinitionexception; string[] getaliases(string name); }
factorybean
一般情况下,spring通过反射机制利用<bean>的class属性指定实现类实例化bean,在某些情况下,实例化bean过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。spring为此提供了一个org.springframework.bean.factory.factorybean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑。factorybean接口对于spring框架来说占用重要的地位,spring自身就提供了70多个factorybean的实现。它们隐藏了实例化一些复杂bean的细节,给上层应用带来了便利。从spring3.0开始,factorybean开始支持泛型,即接口声明改为factorybean<t>的形式。
以bean结尾,表示它是一个bean,不同于普通bean的是:它是实现了factorybean<t>接口的bean,根据该bean的id从beanfactory中获取的实际上是factorybean的getobject()返回的对象,而不是factorybean本身,如果要获取factorybean对象,请在id前面加一个&符号来获取。后面我们会从源码来分析这一块
package org.springframework.beans.factory; public interface factorybean<t> { t getobject() throws exception; class<?> getobjecttype(); boolean issingleton(); }
在该接口中还定义了以下3个方法:
- t getobject():返回由factorybean创建的bean实例,如果issingleton()返回true,则该实例会放到spring容器中单实例缓存池中;
- boolean issingleton():返回由factorybean创建的bean实例的作用域是singleton还是prototype;
- class<t> getobjecttype():返回factorybean创建的bean类型。
当配置文件中<bean>的class属性配置的实现类是factorybean时,通过getbean()方法返回的不是factorybean本身,而是factorybean#getobject()方法所返回的对象,相当于factorybean#getobject()代理了getbean()方法。
例:如果使用传统方式配置下面car的<bean>时,car的每个属性分别对应一个<property>元素标签。
public class car { private int maxspeed ; private string brand ; private double price ; //get//set 方法 }
如果用factorybean的方式实现就灵活点,下例通过逗号分割符的方式一次性的为car的所有属性指定配置值:
import org.springframework.beans.factory.factorybean; public class carfactorybean implements factorybean<car> { private string carinfo ; public car getobject() throws exception { car car = new car(); string[] infos = carinfo.split(","); car.setbrand(infos[0]); car.setmaxspeed(integer.valueof(infos[1])); car.setprice(double.valueof(infos[2])); return car; } public class<car> getobjecttype(){ return car.class ; } public boolean issingleton(){ return false ; } public string getcarinfo(){ return this.carinfo; } //接受逗号分割符设置属性信息 public void setcarinfo (string carinfo){ this.carinfo = carinfo; } }
有了这个carfactorybean后,就可以在配置文件中使用下面这种自定义的配置方式配置carbean了:
<bean d="car"class="com.chenhao.spring.carfactorybean" p:carinfo="大奔,600,1000000"/>
当调用getbean("car")时,spring通过反射机制发现carfactorybean实现了factorybean的接口,这时spring容器就调用接口方法carfactorybean#getobject()方法返回。如果希望获取carfactorybean的实例,则需要在使用getbean(beanname)方法时在beanname前显示的加上"&"前缀:如getbean("&car");
获取bean
接下来我们回到加载bean的阶段,当我们显示或者隐式地调用 getbean()
时,则会触发加载 bean 阶段。如下:
public object getbean(string name) throws beansexception { return dogetbean(name, null, null, false); }
内部调用 dogetbean()
方法,这个方法的代码比较长,各位耐心看下:
@suppresswarnings("unchecked") protected <t> t dogetbean(final string name, @nullable final class<t> requiredtype, @nullable final object[] args, boolean typecheckonly) throws beansexception { //获取 beanname,这里是一个转换动作,将 name 转换为 beanname final string beanname = transformedbeanname(name); object bean; /* *检查缓存中的实例工程是否存在对应的实例 *为何要优先使用这段代码呢? *因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖 *spring创建bean的原则是在不等bean创建完就会将创建bean的objectfactory提前曝光,即将其加入到缓存中,一旦下个bean创建时依赖上个bean则直接使用objectfactory *直接从缓存中或singletonfactories中获取objectfactory *就算没有循环依赖,只是单纯的依赖注入,如b依赖a,如果a已经初始化完成,b进行初始化时,需要递归调用getbean获取a,这是a已经在缓存里了,直接可以从这里取到 */ // eagerly check singleton cache for manually registered singletons. object sharedinstance = getsingleton(beanname); if (sharedinstance != null && args == null) { if (logger.isdebugenabled()) { if (issingletoncurrentlyincreation(beanname)) { logger.debug("returning eagerly cached instance of singleton bean '" + beanname + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("returning cached instance of singleton bean '" + beanname + "'"); } } //返回对应的实例,有些时候并不是直接返回实例,而是返回某些方法返回的实例 //这里涉及到我们上面讲的factorybean,如果此bean是factorybean的实现类,如果name前缀为"&",则直接返回此实现类的bean,如果没有前缀"&",则需要调用此实现类的getobject方法,返回getobject里面真是的返回对象 bean = getobjectforbeaninstance(sharedinstance, name, beanname, null); } else { //只有在单例的情况下才会解决循环依赖 if (isprototypecurrentlyincreation(beanname)) { throw new beancurrentlyincreationexception(beanname); } //尝试从parentbeanfactory中查找bean beanfactory parentbeanfactory = getparentbeanfactory(); if (parentbeanfactory != null && !containsbeandefinition(beanname)) { // not found -> check parent. string nametolookup = originalbeanname(name); if (parentbeanfactory instanceof abstractbeanfactory) { return ((abstractbeanfactory) parentbeanfactory).dogetbean( nametolookup, requiredtype, args, typecheckonly); } else if (args != null) { // delegation to parent with explicit args. return (t) parentbeanfactory.getbean(nametolookup, args); } else { // no args -> delegate to standard getbean method. return parentbeanfactory.getbean(nametolookup, requiredtype); } } //如果不是仅仅做类型检查,则这里需要创建bean,并做记录 if (!typecheckonly) { markbeanascreated(beanname); } try { //将存储xml配置文件的genericbeandefinition转换为rootbeandefinition,同时如果存在父bean的话则合并父bean的相关属性 final rootbeandefinition mbd = getmergedlocalbeandefinition(beanname); checkmergedbeandefinition(mbd, beanname, args); //如果存在依赖则需要递归实例化依赖的bean string[] dependson = mbd.getdependson(); if (dependson != null) { for (string dep : dependson) { if (isdependent(beanname, dep)) { throw new beancreationexception(mbd.getresourcedescription(), beanname, "circular depends-on relationship between '" + beanname + "' and '" + dep + "'"); } registerdependentbean(dep, beanname); try { getbean(dep); } catch (nosuchbeandefinitionexception ex) { throw new beancreationexception(mbd.getresourcedescription(), beanname, "'" + beanname + "' depends on missing bean '" + dep + "'", ex); } } } // 单例模式 // 实例化依赖的bean后对bean本身进行实例化 if (mbd.issingleton()) { sharedinstance = getsingleton(beanname, () -> { try { return createbean(beanname, mbd, args); } catch (beansexception ex) { // explicitly remove instance from singleton cache: it might have been put there // eagerly by the creation process, to allow for circular reference resolution. // also remove any beans that received a temporary reference to the bean. destroysingleton(beanname); throw ex; } }); bean = getobjectforbeaninstance(sharedinstance, name, beanname, mbd); } // 原型模式 else if (mbd.isprototype()) { // it's a prototype -> create a new instance. object prototypeinstance = null; try { beforeprototypecreation(beanname); prototypeinstance = createbean(beanname, mbd, args); } finally { afterprototypecreation(beanname); } bean = getobjectforbeaninstance(prototypeinstance, name, beanname, mbd); } // 从指定的 scope 下创建 bean else { string scopename = mbd.getscope(); final scope scope = this.scopes.get(scopename); if (scope == null) { throw new illegalstateexception("no scope registered for scope name '" + scopename + "'"); } try { object scopedinstance = scope.get(beanname, () -> { beforeprototypecreation(beanname); try { return createbean(beanname, mbd, args); } finally { afterprototypecreation(beanname); } }); bean = getobjectforbeaninstance(scopedinstance, name, beanname, mbd); } catch (illegalstateexception ex) { throw new beancreationexception(beanname, "scope '" + scopename + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (beansexception ex) { cleanupafterbeancreationfailure(beanname); throw ex; } } // check if required type matches the type of the actual bean instance. if (requiredtype != null && !requiredtype.isinstance(bean)) { try { t convertedbean = gettypeconverter().convertifnecessary(bean, requiredtype); if (convertedbean == null) { throw new beannotofrequiredtypeexception(name, requiredtype, bean.getclass()); } return convertedbean; } catch (typemismatchexception ex) { if (logger.isdebugenabled()) { logger.debug("failed to convert bean '" + name + "' to required type '" + classutils.getqualifiedname(requiredtype) + "'", ex); } throw new beannotofrequiredtypeexception(name, requiredtype, bean.getclass()); } } return (t) bean; }
代码是相当长,处理逻辑也是相当复杂,下面将其进行拆分讲解。
获取 beanname
final string beanname = transformedbeanname(name);
这里传递的是 name,不一定就是 beanname,可能是 aliasname,也有可能是 factorybean(带“&”前缀),所以这里需要调用 transformedbeanname()
方法对 name 进行一番转换,主要如下:
protected string transformedbeanname(string name) { return canonicalname(beanfactoryutils.transformedbeanname(name)); } // 去除 factorybean 的修饰符 public static string transformedbeanname(string name) { assert.notnull(name, "'name' must not be null"); string beanname = name; while (beanname.startswith(beanfactory.factory_bean_prefix)) { beanname = beanname.substring(beanfactory.factory_bean_prefix.length()); } return beanname; } // 转换 aliasname public string canonicalname(string name) { string canonicalname = name; // handle aliasing... string resolvedname; do { resolvedname = this.aliasmap.get(canonicalname); if (resolvedname != null) { canonicalname = resolvedname; } } while (resolvedname != null); return canonicalname; }
主要处理过程包括两步:
- 去除 factorybean 的修饰符。如果 name 以 “&” 为前缀,那么会去掉该 “&”,例如,
name = "&studentservice"
,则会是name = "studentservice"
。 - 取指定的 alias 所表示的最终 beanname。主要是一个循环获取 beanname 的过程,例如别名 a 指向名称为 b 的 bean 则返回 b,若 别名 a 指向别名 b,别名 b 指向名称为 c 的 bean,则返回 c。
缓存中获取单例bean
单例在spring的同一个容器内只会被创建一次,后续再获取bean直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试从singletonfactorry加载因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,spring创建bean的原则不等bean创建完成就会创建bean的objectfactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上个bean,则直接使用objectfactory;就算没有循环依赖,只是单纯的依赖注入,如b依赖a,如果a已经初始化完成,b进行初始化时,需要递归调用getbean获取a,这是a已经在缓存里了,直接可以从这里取到。接下来我们看下获取单例bean的方法getsingleton(beanname),进入方法体:
@override @nullable public object getsingleton(string beanname) { //参数true是允许早期依赖 return getsingleton(beanname, true); } @nullable protected object getsingleton(string beanname, boolean allowearlyreference) { //检查缓存中是否存在实例,这里就是上面说的单纯的依赖注入,如b依赖a,如果a已经初始化完成,b进行初始化时,需要递归调用getbean获取a,这是a已经在缓存里了,直接可以从这里取到 object singletonobject = this.singletonobjects.get(beanname); //如果缓存为空且单例bean正在创建中,则锁定全局变量,为什么要判断bean在创建中呢?这里就是可以判断是否循环依赖了。 //a依赖b,b也依赖a,a实例化的时候,发现依赖b,则递归去实例化b,b发现依赖a,则递归实例化a,此时会走到原点a的实例化,第一次a的实例化还没完成,只不过把实例化的对象加入到缓存中,但是状态还是正在创建中,由此回到原点发现a正在创建中,由此可以判断是循环依赖了 if (singletonobject == null && issingletoncurrentlyincreation(beanname)) { synchronized (this.singletonobjects) { //如果此bean正在加载,则不处理 singletonobject = this.earlysingletonobjects.get(beanname); if (singletonobject == null && allowearlyreference) { //当某些方法需要提前初始化的时候会直接调用addsingletonfactory把对应的objectfactory初始化策略存储在singletonfactory中 objectfactory<?> singletonfactory = this.singletonfactories.get(beanname); if (singletonfactory != null) { //使用预先设定的getobject方法 singletonobject = singletonfactory.getobject(); 记录在缓存中,注意earlysingletonobjects和singletonfactories是互斥的 this.earlysingletonobjects.put(beanname, singletonobject); this.singletonfactories.remove(beanname); } } } } return singletonobject; }
接下来我们根据源码再来梳理下这个方法,这样更易于理解,这个方法先尝试从singletonobjects里面获取实例,如果如果获取不到再从earlysingletonobjects里面获取,如果还获取不到,再尝试从singletonfactories里面获取beanname对应的objectfactory,然后再调用这个objectfactory的getobject方法创建bean,并放到earlysingletonobjects里面去,并且从singletonfactoryes里面remove调这个objectfactory,而对于后续所有的内存操作都只为了循环依赖检测时候使用,即allowearlyreference为true的时候才会使用。
这里涉及到很多个存储bean的不同map,简单解释下:
singletonobjects:用于保存beanname和创建bean实例之间的关系,beanname–>bean instance
singletonfactories:用于保存beanname和创建bean的工厂之间的关系,banname–>objectfactory
earlysingletonobjects:也是保存beanname和创建bean实例之间的关系,与singletonobjects的不同之处在于,当一个单例bean被放到这里面后,那么当bean还在创建过程中,就可以通过getbean方法获取到了,其目的是用来检测循环引用。
registeredsingletons:用来保存当前所有已注册的bean.
从bean的实例中获取对象
获取到bean以后就要获取实例对象了,这里用到的是getobjectforbeaninstance方法。getobjectforbeaninstance是个频繁使用的方法,无论是从缓存中获得bean还是根据不同的scope策略加载bean.总之,我们得到bean的实例后,要做的第一步就是调用这个方法来检测一下正确性,其实就是检测获得bean是不是factorybean类型的bean,如果是,那么需要调用该bean对应的factorybean实例中的getobject()作为返回值。接下来我们看下此方法的源码:
protected object getobjectforbeaninstance( object beaninstance, string name, string beanname, @nullable rootbeandefinition mbd) { //如果指定的name是工厂相关的(以&开头的) if (beanfactoryutils.isfactorydereference(name)) { //如果是nullbean则直接返回此bean if (beaninstance instanceof nullbean) { return beaninstance; } //如果不是factorybean类型,则验证不通过抛出异常 if (!(beaninstance instanceof factorybean)) { throw new beanisnotafactoryexception(transformedbeanname(name), beaninstance.getclass()); } } // now we have the bean instance, which may be a normal bean or a factorybean. // if it's a factorybean, we use it to create a bean instance, unless the // caller actually wants a reference to the factory. //如果获取的beaninstance不是factorybean类型,则说明是普通的bean,可直接返回 //如果获取的beaninstance是factorybean类型,但是是以(以&开头的),也直接返回,此时返回的是factorybean的实例 if (!(beaninstance instanceof factorybean) || beanfactoryutils.isfactorydereference(name)) { return beaninstance; } object object = null; if (mbd == null) { object = getcachedobjectforfactorybean(beanname); } if (object == null) { // return bean instance from factory. factorybean<?> factory = (factorybean<?>) beaninstance; // caches object obtained from factorybean if it is a singleton. if (mbd == null && containsbeandefinition(beanname)) { mbd = getmergedlocalbeandefinition(beanname); } boolean synthetic = (mbd != null && mbd.issynthetic()); //到了这里说明获取的beaninstance是factorybean类型,但没有以"&"开头,此时就要返回factory内部getobject里面的对象了 object = getobjectfromfactorybean(factory, beanname, !synthetic); } return object; }
接着我们来看看真正的核心功能getobjectfromfactorybean(factory, beanname, !synthetic)方法中实现的,继续跟进代码:
protected object getobjectfromfactorybean(factorybean<?> factory, string beanname, boolean shouldpostprocess) { // 为单例模式且缓存中存在 if (factory.issingleton() && containssingleton(beanname)) { synchronized (getsingletonmutex()) { // 从缓存中获取指定的 factorybean object object = this.factorybeanobjectcache.get(beanname); if (object == null) { // 为空,则从 factorybean 中获取对象 object = dogetobjectfromfactorybean(factory, beanname); // 从缓存中获取 object alreadythere = this.factorybeanobjectcache.get(beanname); if (alreadythere != null) { object = alreadythere; } else { // 需要后续处理 if (shouldpostprocess) { // 若该 bean 处于创建中,则返回非处理对象,而不是存储它 if (issingletoncurrentlyincreation(beanname)) { return object; } // 前置处理 beforesingletoncreation(beanname); try { // 对从 factorybean 获取的对象进行后处理 // 生成的对象将暴露给bean引用 object = postprocessobjectfromfactorybean(object, beanname); } catch (throwable ex) { throw new beancreationexception(beanname, "post-processing of factorybean's singleton object failed", ex); } finally { // 后置处理 aftersingletoncreation(beanname); } } // 缓存 if (containssingleton(beanname)) { this.factorybeanobjectcache.put(beanname, object); } } } return object; } } else { // 非单例 object object = dogetobjectfromfactorybean(factory, beanname); if (shouldpostprocess) { try { object = postprocessobjectfromfactorybean(object, beanname); } catch (throwable ex) { throw new beancreationexception(beanname, "post-processing of factorybean's object failed", ex); } } return object; } }
该方法应该就是创建 bean 实例对象中的核心方法之一了。这里我们关注三个方法:beforesingletoncreation()
、 aftersingletoncreation()
、 postprocessobjectfromfactorybean()
。可能有小伙伴觉得前面两个方法不是很重要,lz 可以肯定告诉你,这两方法是非常重要的操作,因为他们记录着 bean 的加载状态,是检测当前 bean 是否处于创建中的关键之处,对解决 bean 循环依赖起着关键作用。before 方法用于标志当前 bean 处于创建中,after 则是移除。其实在这篇博客刚刚开始就已经提到了 issingletoncurrentlyincreation()
是用于检测当前 bean 是否处于创建之中,如下:
public boolean issingletoncurrentlyincreation(string beanname) { return this.singletonscurrentlyincreation.contains(beanname); }
是根据 singletonscurrentlyincreation 集合中是否包含了 beanname,集合的元素则一定是在 beforesingletoncreation()
中添加的,如下:
protected void beforesingletoncreation(string beanname) { if (!this.increationcheckexclusions.contains(beanname) && !this.singletonscurrentlyincreation.add(beanname)) { throw new beancurrentlyincreationexception(beanname); } }
aftersingletoncreation()
为移除,则一定就是对 singletonscurrentlyincreation 集合 remove 了,如下:
protected void aftersingletoncreation(string beanname) { if (!this.increationcheckexclusions.contains(beanname) && !this.singletonscurrentlyincreation.remove(beanname)) { throw new illegalstateexception("singleton '" + beanname + "' isn't currently in creation"); } }
我们再来看看真正的核心方法 dogetobjectfromfactorybean
private object dogetobjectfromfactorybean(final factorybean<?> factory, final string beanname) throws beancreationexception { object object; try { if (system.getsecuritymanager() != null) { accesscontrolcontext acc = getaccesscontrolcontext(); try { object = accesscontroller.doprivileged((privilegedexceptionaction<object>) factory::getobject, acc); } catch (privilegedactionexception pae) { throw pae.getexception(); } } else { object = factory.getobject(); } } catch (factorybeannotinitializedexception ex) { throw new beancurrentlyincreationexception(beanname, ex.tostring()); } catch (throwable ex) { throw new beancreationexception(beanname, "factorybean threw exception on object creation", ex); } // do not accept a null value for a factorybean that's not fully // initialized yet: many factorybeans just return null then. if (object == null) { if (issingletoncurrentlyincreation(beanname)) { throw new beancurrentlyincreationexception( beanname, "factorybean which is currently in creation returned null from getobject"); } object = new nullbean(); } return object; }
以前我们曾经介绍过factorybean的调用方法,如果bean声明为factorybean类型,则当提取bean时候提取的不是factorybean,而是factorybean中对应的getobject方法返回的bean,而dogetobjectfromfactroybean真是实现这个功能。
而调用完dogetobjectfromfactorybean方法后,并没有直接返回,getobjectfromfactorybean方法中还调用了object = postprocessobjectfromfactorybean(object, beanname);方法,在子类abstractautowirecapablebeanfactory,有这个方法的实现:
@override protected object postprocessobjectfromfactorybean(object object, string beanname) { return applybeanpostprocessorsafterinitialization(object, beanname); } @override public object applybeanpostprocessorsafterinitialization(object existingbean, string beanname) throws beansexception { object result = existingbean; for (beanpostprocessor beanprocessor : getbeanpostprocessors()) { object current = beanprocessor.postprocessafterinitialization(result, beanname); if (current == null) { return result; } result = current; } return result; }
对于后处理器的使用,我们目前还没接触,后续会有大量篇幅介绍,这里我们只需要了解在spring获取bean的规则中有这样一条:尽可能保证所有bean初始化后都会调用注册的beanpostprocessor的postprocessafterinitialization方法进行处理,在实际开发过程中大可以针对此特性设计自己的业务处理。
推荐阅读
-
spring5 源码深度解析----- 被面试官给虐懵了,竟然是因为我不懂@Configuration配置类及@Bean的原理
-
spring源码深度解析— IOC 之 默认标签解析(上)
-
spring源码深度解析— IOC 之 循环依赖处理
-
【死磕 Spring】----- IOC 之解析 bean 标签:开启解析进程
-
spring源码深度解析— IOC 之 开启 bean 的加载
-
spring源码深度解析— IOC 之 默认标签解析(下)
-
spring源码深度解析— IOC 之 bean 的初始化
-
【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
-
【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
-
Spring源码解析之bean的创建与获取