详解Spring中Bean的加载的方法
之前写过bean的解析,这篇来讲讲bean的加载,加载要比bean的解析复杂些,从之前的例子开始.
spring中加载一个bean的方式:
testbean bean = factory.getbean("testbean");
来看看getbean(string name)方法源码,
@override public object getbean(string name) throws beansexception { return dogetbean(name, null, null, false); }
该getbean(string name)方法位于abstractbeanfactory抽象类中,abstractbeanfactory与xmlbeanfactory类关系可以看下图:
接下去跟进dogetbean()方法源码:
protected <t> t dogetbean( final string name, final class<t> requiredtype, final object[] args, boolean typecheckonly) throws beansexception { // 提取beanname final string beanname = transformedbeanname(name); object bean; // 试着从缓存或实例工厂中获取 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 + "'"); } } // 返回实例,有时存在如beanfactory这样情况时并不是直接返回实例本身而是返回指定方法返回的实例 bean = getobjectforbeaninstance(sharedinstance, name, beanname, null); } else { // fail if we're already creating this bean instance: // we're assumably within a circular reference. if (isprototypecurrentlyincreation(beanname)) { throw new beancurrentlyincreationexception(beanname); } // check if bean definition exists in this factory. beanfactory parentbeanfactory = getparentbeanfactory(); // 如果在所有已经加载的类中没有beanname则会尝试从parentbeanfactory中检测 if (parentbeanfactory != null && !containsbeandefinition(beanname)) { // not found -> check parent. string nametolookup = originalbeanname(name); // 到beanfactory查找 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配置文件的gernericbeandefinition转换成rootbeandefinition,如果beanname是子bean的话会合并父类的相关属性 final rootbeandefinition mbd = getmergedlocalbeandefinition(beanname); checkmergedbeandefinition(mbd, beanname, args); // guarantee initialization of beans that the current bean depends on. string[] dependson = mbd.getdependson(); // 如果存在依赖的话要递归实例化依赖的bean if (dependson != null) { for (string dependsonbean : dependson) { if (isdependent(beanname, dependsonbean)) { throw new beancreationexception(mbd.getresourcedescription(), beanname, "circular depends-on relationship between '" + beanname + "' and '" + dependsonbean + "'"); } registerdependentbean(dependsonbean, beanname); getbean(dependsonbean); } } // create bean instance. // 依赖的bean实例化完后就可以实例化mbd了 if (mbd.issingleton()) { sharedinstance = getsingleton(beanname, new objectfactory<object>() { @override public object getobject() throws beansexception { 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); } else { // 在对应的scope上实例化bean string scopename = mbd.getscope(); final scope scope = this.scopes.get(scopename); if (scope == null) { throw new illegalstateexception("no scope registered for scope '" + scopename + "'"); } try { object scopedinstance = scope.get(beanname, new objectfactory<object>() { @override public object getobject() throws beansexception { 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; } } // 检查需要的类型是否符合实例bean的实际类型 if (requiredtype != null && bean != null && !requiredtype.isassignablefrom(bean.getclass())) { try { return gettypeconverter().convertifnecessary(bean, requiredtype); } 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; }
整个bean加载的过程步骤相对繁琐,主要步骤有以下几点:
1、转换beanname
要知道平时开发中传入的参数name可能只是别名,也可能是factorybean,所以需要进行解析转换,一般会进行以下解析:
(1)消除修饰符,比如name="&test",会去除&使name="test";
(2)取alias表示的最后的beanname,比如别名test01指向名称为test02的bean则返回test02。
2、从缓存中加载实例
实例在spring的同一个容器中只会被创建一次,后面再想获取该bean时,就会尝试从缓存中获取;如果获取不到的话再从singletonfactories中加载。
3、实例化bean
缓存中记录的bean一般只是最原始的bean状态,这时就需要对bean进行实例化。如果得到的是bean的原始状态,但又要对bean进行处理,这时真正需要的是工厂bean中定义的factory-method方法中返回的bean,上面源码中的getobjectforbeaninstance就是来完成这个工作的。
4、检测parentbeanfacotory
从源码可以看出如果缓存中没有数据会转到父类工厂去加载,源码中的!containsbeandefinition(beanname)就是检测如果当前加载的xml配置文件中不包含beanname所对应的配置,就只能到parentbeanfacotory去尝试加载bean。
5、存储xml配置文件的gernericbeandefinition转换成rootbeandefinition之前的文章介绍过xml配置文件中读取到的bean信息是存储在gernericbeandefinition中的,但bean的后续处理是针对于rootbeandefinition的,所以需要转换后才能进行后续操作。
6、初始化依赖的bean
这里应该比较好理解,就是bean中可能依赖了其他bean属性,在初始化bean之前会先初始化这个bean所依赖的bean属性。
7、创建bean
spring容器根据不同scope创建bean实例。
整个流程就是如此,下面会讲解一些重要步骤的源码。
上面有提到,单例在spring中的同一容器中只会被创建一次,后面再获取bean的话会直接从缓存中获取,这里是尝试加载,先从缓存中加载,再次就是从singletonfactories中加载;因为在bean中可能会在依赖注入,要避免循环依赖,spring创建bean时会不等bean创建完成就会将创建该bean的objectfactory提前曝光加入到缓存中,但下一个bean创建时要依赖上个bean的话,就直接使用objectfacotry。
@override public object getsingleton(string beanname) { return getsingleton(beanname, true); // true表示允许早期依赖 } protected object getsingleton(string beanname, boolean allowearlyreference) { // 尝试从缓存获取实例 object singletonobject = this.singletonobjects.get(beanname); if (singletonobject == null && issingletoncurrentlyincreation(beanname)) { synchronized (this.singletonobjects) { // 若该bean正在加载则不处理 singletonobject = this.earlysingletonobjects.get(beanname); if (singletonobject == null && allowearlyreference) { objectfactory<?> singletonfactory = this.singletonfactories.get(beanname); if (singletonfactory != null) { singletonobject = singletonfactory.getobject(); // 存入到缓存中 this.earlysingletonobjects.put(beanname, singletonobject); this.singletonfactories.remove(beanname); } } } } return (singletonobject != null_object ? singletonobject : null); } /* 这两个方法在defaultsingletonbeanregistry类中 */
从源码可以看出这个方法先尝试从singletonobjects中获取实例,如果获取不到值就从earlysingletonobject中去获取,如果再获取不到的话则到singletonfactories里获取beanname对应的objectfactory,再调用这个objectfactory的getobject来创建bean,并放到earlysingletonobject中,并且从singletonfactories里remove掉这个objectfactory。这里有几个存储bean的不同map:
- -singletonobjects:保存beanname和创建bean实例之间的关系。
- -singletonfactories:保存beanname和创建bean实例的工厂之间的关系。
- -earlysingletonobject:保存beanname和创建bean实例之间的关系,与-singletonobjects不同的是当一个单例bean被放到里面后,那当bean在创建过程中,就可以通过getbean方法获取到,可以用来检测循环引用。
- -registeredsingletons:保存当前所有已注册的bean。
如果上面缓存中不存在已经加载的单例bean就要重新开始bean的加载过程了,spring中使用getsingleton重载方法实现bean的加载过程。
public object getsingleton(string beanname, objectfactory<?> singletonfactory) { assert.notnull(beanname, "'beanname' must not be null"); synchronized (this.singletonobjects) { // 先检查bean是否已经加载 object singletonobject = this.singletonobjects.get(beanname); // 如果空才进行singleton的bean的初始化 if (singletonobject == null) { if (this.singletonscurrentlyindestruction) { throw new beancreationnotallowedexception(beanname, "singleton bean creation not allowed while the singletons of this factory are in destruction " + "(do not request a bean from a beanfactory in a destroy method implementation!)"); } if (logger.isdebugenabled()) { logger.debug("creating shared instance of singleton bean '" + beanname + "'"); } beforesingletoncreation(beanname); boolean newsingleton = false; boolean recordsuppressedexceptions = (this.suppressedexceptions == null); if (recordsuppressedexceptions) { this.suppressedexceptions = new linkedhashset<exception>(); } try { // 初始化bean singletonobject = singletonfactory.getobject(); newsingleton = true; } catch (illegalstateexception ex) { // has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonobject = this.singletonobjects.get(beanname); if (singletonobject == null) { throw ex; } } catch (beancreationexception ex) { if (recordsuppressedexceptions) { for (exception suppressedexception : this.suppressedexceptions) { ex.addrelatedcause(suppressedexception); } } throw ex; } finally { if (recordsuppressedexceptions) { this.suppressedexceptions = null; } aftersingletoncreation(beanname); } if (newsingleton) { // 存入缓存 addsingleton(beanname, singletonobject); } } return (singletonobject != null_object ? singletonobject : null); } }
这段代码使用了回调方法,使程序可以在单例创建的前后做一些准备及处理操作,真正的获取单例bean的方法其实并不是在这个方法实现的,而是在objectfactory类型的实例singletonfactory中实现的。
下面准备创建bean
看看createbean()方法源码(该方法在abstractautowirecapablebeanfactory类中):
protected object createbean(final string beanname, final rootbeandefinition mbd, final object[] args) throws beancreationexception { if (logger.isdebugenabled()) { logger.debug("creating instance of bean '" + beanname + "'"); } // 锁定class,根据设置的class属性或根据classname来解析class resolvebeanclass(mbd, beanname); // 验证和准备覆盖的方法 try { mbd.preparemethodoverrides(); } catch (beandefinitionvalidationexception ex) { throw new beandefinitionstoreexception(mbd.getresourcedescription(), beanname, "validation of method overrides failed", ex); } try { // 用beanpostprocessors返回代理来替代真正的实例 object bean = resolvebeforeinstantiation(beanname, mbd); if (bean != null) { return bean; } } catch (throwable ex) { throw new beancreationexception(mbd.getresourcedescription(), beanname, "beanpostprocessor before instantiation of bean failed", ex); } object beaninstance = docreatebean(beanname, mbd, args); if (logger.isdebugenabled()) { logger.debug("finished creating instance of bean '" + beanname + "'"); } return beaninstance; }
从createbean()方法源码可以看出主要做了以下操作:
- 根据设置的class属性或根据classname来解析class;
- 对覆盖进行标记并验证,在spring配置中是存在lookup-mothod和replace-method的,这两个配置的加载其实就是将配置统一存放在beandefinition中的methodoverrides属性里,这个方法的操作也就是针对于这两个配置的;
- 应用初始化前的后处理器,最后创建bean。
在createbean()方法里执行完resolvebeforeinstantiation方法后,如果创建了代理且不为空的话就直接返回,否则需要进行常规bean的创建,这个创建过程是在docreatebean中完成的,跟进源码:
protected object docreatebean(final string beanname, final rootbeandefinition mbd, final object[] args) { // instantiate the bean. beanwrapper instancewrapper = null; if (mbd.issingleton()) { instancewrapper = this.factorybeaninstancecache.remove(beanname); } if (instancewrapper == null) { // 根据指定bean使用相应策略创建实例 instancewrapper = createbeaninstance(beanname, mbd, args); } final object bean = (instancewrapper != null ? instancewrapper.getwrappedinstance() : null); class<?> beantype = (instancewrapper != null ? instancewrapper.getwrappedclass() : null); // allow post-processors to modify the merged bean definition. synchronized (mbd.postprocessinglock) { if (!mbd.postprocessed) { applymergedbeandefinitionpostprocessors(mbd, beantype, beanname); mbd.postprocessed = true; } } // 检测循环依赖,是否需要提早曝光 boolean earlysingletonexposure = (mbd.issingleton() && this.allowcircularreferences && issingletoncurrentlyincreation(beanname)); if (earlysingletonexposure) { if (logger.isdebugenabled()) { logger.debug("eagerly caching bean '" + beanname + "' to allow for resolving potential circular references"); } // 避免循环依赖,可以在bean初始化完成前将创建实例的objectfactory加入工厂 addsingletonfactory(beanname, new objectfactory<object>() { @override public object getobject() throws beansexception { // 对bean再次依赖引用 // aop也是在这里将advice动态织入bean中,若没有则直接返回bean,不做处理 return getearlybeanreference(beanname, mbd, bean); } }); } // initialize the bean instance. object exposedobject = bean; try { // 填充bean,注入属性值,如果存在依赖于其他bean的属性,会递归初始化 populatebean(beanname, mbd, instancewrapper); if (exposedobject != null) { // 调用初始化方法 exposedobject = initializebean(beanname, exposedobject, mbd); } } catch (throwable ex) { if (ex instanceof beancreationexception && beanname.equals(((beancreationexception) ex).getbeanname())) { throw (beancreationexception) ex; } else { throw new beancreationexception(mbd.getresourcedescription(), beanname, "initialization of bean failed", ex); } } if (earlysingletonexposure) { object earlysingletonreference = getsingleton(beanname, false); // earlysingletonreference只有在检测到有循环依赖的情况下才会不为空 if (earlysingletonreference != null) { if (exposedobject == bean) { exposedobject = earlysingletonreference; } else if (!this.allowrawinjectiondespitewrapping && hasdependentbean(beanname)) { string[] dependentbeans = getdependentbeans(beanname); set<string> actualdependentbeans = new linkedhashset<string>(dependentbeans.length); for (string dependentbean : dependentbeans) { // 检测依赖 if (!removesingletonifcreatedfortypecheckonly(dependentbean)) { actualdependentbeans.add(dependentbean); } } if (!actualdependentbeans.isempty()) { throw new beancurrentlyincreationexception(beanname, "bean with name '" + beanname + "' has been injected into other beans [" + stringutils.collectiontocommadelimitedstring(actualdependentbeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. this means that said other beans do not use the final version of the " + "bean. this is often the result of over-eager type matching - consider using " + "'getbeannamesoftype' with the 'alloweagerinit' flag turned off, for example."); } } } } // register bean as disposable. try { // 依据scopse注册bean registerdisposablebeanifnecessary(beanname, bean, mbd); } catch (beandefinitionvalidationexception ex) { throw new beancreationexception(mbd.getresourcedescription(), beanname, "invalid destruction signature", ex); } return exposedobject; }
上面源码完成的操作可以概括为以下几点:
- 开始是单例的话要先清除缓存;
- 实例化bean,将beandefinition转换为beanwrapper;
- 使用mergedbeandefinitionpostprocessor,autowired注解就是通过此方法实现类型的预解析;
- 解决循环依赖问题;
- 填充属性,将属性填充到bean实例中;
- 注册disposablebean;
- 创建完成并返回
接下来创建bean实例,看createbeaninstance()方法:
protected beanwrapper createbeaninstance(string beanname, rootbeandefinition mbd, object[] args) { // 解析class 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()); } // 若工厂方法不为空则使用工厂方法初始化 if (mbd.getfactorymethodname() != null) { return instantiateusingfactorymethod(beanname, mbd, args); } // shortcut when re-creating the same bean... boolean resolved = false; boolean autowirenecessary = false; if (args == null) { synchronized (mbd.constructorargumentlock) { if (mbd.resolvedconstructororfactorymethod != null) { resolved = true; autowirenecessary = mbd.constructorargumentsresolved; } } } // 如果已经解析过则使用解析好的构造方法不需要再次锁定 if (resolved) { if (autowirenecessary) { // 构造方法自动注入 return autowireconstructor(beanname, mbd, null, null); } else { // 使用默认构造方法 return instantiatebean(beanname, mbd); } } // 根据参数解析构造方法 constructor<?>[] ctors = determineconstructorsfrombeanpostprocessors(beanclass, beanname); if (ctors != null || mbd.getresolvedautowiremode() == rootbeandefinition.autowire_constructor || mbd.hasconstructorargumentvalues() || !objectutils.isempty(args)) { return autowireconstructor(beanname, mbd, ctors, args); } // no special handling: simply use no-arg constructor. return instantiatebean(beanname, mbd); }
可以看出如果在rootbeandefinition中存在factorymethodname属性,或者说配置文件中配置了factory-method,那么spring会尝试使用instantiateusingfactorymethod(beanname, mbd, args)方法根据rootbeandefinition中的配置生成bean实例。
再解析构造方法并进行实例化,spring会根据参数及类型判断使用哪个构造方法再进行实例化。判断调用哪个构造方法的过程会采用缓存机制,如果已经解析过则不需要重复解析而是从rootbeandefinition中的属性resolvedconstructororfactorymethod缓存的值去取,不然则需要再次解析。
创建bean后接下来就进行属性注入,属性注入的操作在populatebean()方法中,跟进源码:
protected void populatebean(string beanname, rootbeandefinition mbd, beanwrapper bw) { propertyvalues pvs = mbd.getpropertyvalues(); if (bw == null) { if (!pvs.isempty()) { throw new beancreationexception( mbd.getresourcedescription(), beanname, "cannot apply property values to null instance"); } else { // skip property population phase for null instance. return; } } // give any instantiationawarebeanpostprocessors the opportunity to modify the // state of the bean before properties are set. this can be used, for example, // to support styles of field injection. boolean continuewithpropertypopulation = true; 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; } if (mbd.getresolvedautowiremode() == rootbeandefinition.autowire_by_name || mbd.getresolvedautowiremode() == rootbeandefinition.autowire_by_type) { mutablepropertyvalues newpvs = new mutablepropertyvalues(pvs); // add property values based on autowire by name if applicable. if (mbd.getresolvedautowiremode() == rootbeandefinition.autowire_by_name) { autowirebyname(beanname, mbd, bw, newpvs); } // add property values based on autowire by type if applicable. if (mbd.getresolvedautowiremode() == rootbeandefinition.autowire_by_type) { autowirebytype(beanname, mbd, bw, newpvs); } pvs = newpvs; } boolean hasinstawarebpps = hasinstantiationawarebeanpostprocessors(); boolean needsdepcheck = (mbd.getdependencycheck() != rootbeandefinition.dependency_check_none); if (hasinstawarebpps || needsdepcheck) { propertydescriptor[] filteredpds = filterpropertydescriptorsfordependencycheck(bw, mbd.allowcaching); if (hasinstawarebpps) { for (beanpostprocessor bp : getbeanpostprocessors()) { if (bp instanceof instantiationawarebeanpostprocessor) { instantiationawarebeanpostprocessor ibp = (instantiationawarebeanpostprocessor) bp; pvs = ibp.postprocesspropertyvalues(pvs, filteredpds, bw.getwrappedinstance(), beanname); if (pvs == null) { return; } } } } if (needsdepcheck) { checkdependencies(beanname, mbd, filteredpds, pvs); } } applypropertyvalues(beanname, mbd, bw, pvs); }
在populatebean方法的中的主要处理流程:
- instantiationawarebeanpostprocessor处理器的postprocessafterinstantiation方法控制程序是否继续填充属性;
- 根据注入类型提取依赖的bean,并存入propertyvalues中;
- 应用instantiationawarebeanpostprocessor处理器的postprocesspropertyvalues方法对属性在填充前再次处理,主要还是验证属性;
- 将所有propertyvalues中的属性填充到beanwrapper中。
最后初始化bean
学过spring的都知道bean配置时有一个init-method属性,这个属性的作用是在bean实例化前调用init-method指定的方法进行需要的实例化操作,现在就进入这个方法了;spring中程序已经执行过bean的实例化,并且进行了属性的填充,而就在这时将会调用用户设定的初始化方法。
protected object initializebean(final string beanname, final object bean, rootbeandefinition mbd) { if (system.getsecuritymanager() != null) { accesscontroller.doprivileged(new privilegedaction<object>() { @override public object run() { invokeawaremethods(beanname, bean); return null; } }, getaccesscontrolcontext()); } else { // 特殊bean处理 invokeawaremethods(beanname, bean); } object wrappedbean = bean; if (mbd == null || !mbd.issynthetic()) { wrappedbean = applybeanpostprocessorsbeforeinitialization(wrappedbean, beanname); } try { invokeinitmethods(beanname, wrappedbean, mbd); } catch (throwable ex) { throw new beancreationexception( (mbd != null ? mbd.getresourcedescription() : null), beanname, "invocation of init method failed", ex); } if (mbd == null || !mbd.issynthetic()) { wrappedbean = applybeanpostprocessorsafterinitialization(wrappedbean, beanname); } return wrappedbean; }
最后加载完bean并执行完初始化操作后,一个bean的加载基本就结束了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。