spring源码深度解析— IOC 之 属性填充
docreatebean()
主要用于完成 bean 的创建和初始化工作,我们可以将其分为四个过程:
-
createbeaninstance()
实例化 bean -
populatebean()
属性填充 - 循环依赖的处理
-
initializebean()
初始化 bean
第一个过程实例化 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; //返回值为是否继续填充bean 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) { //依赖检查,对应depends-on属性,3.0已经弃用此属性 checkdependencies(beanname, mbd, filteredpds, pvs); } } //将属性应用到bean中 //将所有protertyvalues中的属性填充至beanwrapper中。 applypropertyvalues(beanname, mbd, bw, pvs); }
我们详细分析下populatebean的流程:
(1)首先进行属性是否为空的判断
(2)通过调用instantiationawarebeanpostprocessor的postprocessafterinstantiation(bw.getwrappedinstance(), beanname)方法来控制程序是否继续进行属性填充
(3)根据注入类型(byname/bytype)提取依赖的bean,并统一存入propertyvalues中
(4)应用instantiationawarebeanpostprocessor的postprocesspropertyvalues(pvs, filteredpds, bw.getwrappedinstance(), beanname)方法,对属性获取完毕填充前的再次处理,典型的应用是requiredannotationbeanpostprocesser类中对属性的验证
(5)将所有的propertyvalues中的属性填充至beanwrapper中
上面步骤中有几个地方是我们比较感兴趣的,它们分别是依赖注入(autowirebyname/autowirebytype)以及属性填充,接下来进一步分析这几个功能的实现细节
自动注入
spring 会根据注入类型( byname / bytype )的不同,调用不同的方法(autowirebyname()
/ autowirebytype()
)来注入属性值。
autowirebyname()
protected void autowirebyname( string beanname, abstractbeandefinition mbd, beanwrapper bw, mutablepropertyvalues pvs) { // 获取 bean 对象中非简单属性 string[] propertynames = unsatisfiednonsimpleproperties(mbd, bw); for (string propertyname : propertynames) { // 如果容器中包含指定名称的 bean,则将该 bean 注入到 bean中 if (containsbean(propertyname)) { // 递归初始化相关 bean object bean = getbean(propertyname); // 为指定名称的属性赋予属性值 pvs.add(propertyname, bean); // 属性依赖注入 registerdependentbean(propertyname, beanname); if (logger.isdebugenabled()) { logger.debug("added autowiring by name from bean name '" + beanname + "' via property '" + propertyname + "' to bean named '" + propertyname + "'"); } } else { if (logger.istraceenabled()) { logger.trace("not autowiring property '" + propertyname + "' of bean '" + beanname + "' by name: no matching bean found"); } } } }
该方法逻辑很简单,获取该 bean 的非简单属性,什么叫做非简单属性呢?就是类型为对象类型的属性,但是这里并不是将所有的对象类型都都会找到,比如 8 个原始类型,string 类型 ,number类型、date类型、url类型、uri类型等都会被忽略,如下:
protected string[] unsatisfiednonsimpleproperties(abstractbeandefinition mbd, beanwrapper bw) { set<string> result = new treeset<>(); propertyvalues pvs = mbd.getpropertyvalues(); propertydescriptor[] pds = bw.getpropertydescriptors(); for (propertydescriptor pd : pds) { if (pd.getwritemethod() != null && !isexcludedfromdependencycheck(pd) && !pvs.contains(pd.getname()) && !beanutils.issimpleproperty(pd.getpropertytype())) { result.add(pd.getname()); } } return stringutils.tostringarray(result); }
这里获取的就是需要依赖注入的属性。
autowirebyname()函数的功能就是根据传入的参数中的pvs中找出已经加载的bean,并递归实例化,然后加入到pvs中
autowirebytype
autowirebytype与autowirebyname对于我们理解与使用来说复杂程度相似,但是实现功能的复杂度却不一样,我们看下方法代码:
protected void autowirebytype( string beanname, abstractbeandefinition mbd, beanwrapper bw, mutablepropertyvalues pvs) { typeconverter converter = getcustomtypeconverter(); if (converter == null) { converter = bw; } set<string> autowiredbeannames = new linkedhashset<string>(4); //寻找bw中需要依赖注入的属性 string[] propertynames = unsatisfiednonsimpleproperties(mbd, bw); for (string propertyname : propertynames) { try { propertydescriptor pd = bw.getpropertydescriptor(propertyname); // don't try autowiring by type for type object: never makes sense, // even if it technically is a unsatisfied, non-simple property. if (!object.class.equals(pd.getpropertytype())) { //探测指定属性的set方法 methodparameter methodparam = beanutils.getwritemethodparameter(pd); // do not allow eager init for type matching in case of a prioritized post-processor. boolean eager = !priorityordered.class.isassignablefrom(bw.getwrappedclass()); dependencydescriptor desc = new autowirebytypedependencydescriptor(methodparam, eager); //解析指定beanname的属性所匹配的值,并把解析到的属性名称存储在autowiredbeannames中, object autowiredargument = resolvedependency(desc, beanname, autowiredbeannames, converter); if (autowiredargument != null) { pvs.add(propertyname, autowiredargument); } for (string autowiredbeanname : autowiredbeannames) { //注册依赖 registerdependentbean(autowiredbeanname, beanname); if (logger.isdebugenabled()) { logger.debug("autowiring by type from bean name '" + beanname + "' via property '" + propertyname + "' to bean named '" + autowiredbeanname + "'"); } } autowiredbeannames.clear(); } } catch (beansexception ex) { throw new unsatisfieddependencyexception(mbd.getresourcedescription(), beanname, propertyname, ex); } } }
根据名称第一步与根据属性第一步都是寻找bw中需要依赖注入的属性,然后遍历这些属性并寻找类型匹配的bean,其中最复杂就是寻找类型匹配的bean。spring中提供了对集合的类型注入支持,如使用如下注解方式:
@autowired private list<test> tests;
这种方式spring会把所有与test匹配的类型找出来并注入到tests属性中,正是由于这一因素,所以在autowirebytype函数,新建了局部遍历autowirebeannames,用于存储所有依赖的bean,如果只是对非集合类的属性注入来说,此属性并无用处。
对于寻找类型匹配的逻辑实现是封装在了resolvedependency函数中,其实现如下:
public object resolvedependency(dependencydescriptor descriptor, string beanname, set<string> autowiredbeannames, typeconverter typeconverter) throws beansexception { descriptor.initparameternamediscovery(getparameternamediscoverer()); if (descriptor.getdependencytype().equals(objectfactory.class)) { //objectfactory类注入的特殊处理 return new dependencyobjectfactory(descriptor, beanname); } else if (descriptor.getdependencytype().equals(javaxinjectproviderclass)) { //javaxinjectproviderclass类注入的特殊处理 return new dependencyproviderfactory().createdependencyprovider(descriptor, beanname); } else { //通用处理逻辑 return doresolvedependency(descriptor, descriptor.getdependencytype(), beanname, autowiredbeannames, typeconverter); } } protected object doresolvedependency(dependencydescriptor descriptor, class<?> type, string beanname, set<string> autowiredbeannames, typeconverter typeconverter) throws beansexception { /* * 用于支持spring中新增的注解@value */ object value = getautowirecandidateresolver().getsuggestedvalue(descriptor); if (value != null) { if (value instanceof string) { string strval = resolveembeddedvalue((string) value); beandefinition bd = (beanname != null && containsbean(beanname) ? getmergedbeandefinition(beanname) : null); value = evaluatebeandefinitionstring(strval, bd); } typeconverter converter = (typeconverter != null ? typeconverter : gettypeconverter()); return (descriptor.getfield() != null ? converter.convertifnecessary(value, type, descriptor.getfield()) : converter.convertifnecessary(value, type, descriptor.getmethodparameter())); } //如果解析器没有成功解析,则需要考虑各种情况 //属性是数组类型 if (type.isarray()) { class<?> componenttype = type.getcomponenttype(); //根据属性类型找到beanfactory中所有类型的匹配bean, //返回值的构成为:key=匹配的beanname,value=beanname对应的实例化后的bean(通过getbean(beanname)返回) map<string, object> matchingbeans = findautowirecandidates(beanname, componenttype, descriptor); if (matchingbeans.isempty()) { //如果autowire的require属性为true而找到的匹配项却为空则只能抛出异常 if (descriptor.isrequired()) { raisenosuchbeandefinitionexception(componenttype, "array of " + componenttype.getname(), descriptor); } return null; } if (autowiredbeannames != null) { autowiredbeannames.addall(matchingbeans.keyset()); } typeconverter converter = (typeconverter != null ? typeconverter : gettypeconverter()); //通过转换器将bean的值转换为对应的type类型 return converter.convertifnecessary(matchingbeans.values(), type); } //属性是collection类型 else if (collection.class.isassignablefrom(type) && type.isinterface()) { class<?> elementtype = descriptor.getcollectiontype(); if (elementtype == null) { if (descriptor.isrequired()) { throw new fatalbeanexception("no element type declared for collection [" + type.getname() + "]"); } return null; } map<string, object> matchingbeans = findautowirecandidates(beanname, elementtype, descriptor); if (matchingbeans.isempty()) { if (descriptor.isrequired()) { raisenosuchbeandefinitionexception(elementtype, "collection of " + elementtype.getname(), descriptor); } return null; } if (autowiredbeannames != null) { autowiredbeannames.addall(matchingbeans.keyset()); } typeconverter converter = (typeconverter != null ? typeconverter : gettypeconverter()); return converter.convertifnecessary(matchingbeans.values(), type); } //属性是map类型 else if (map.class.isassignablefrom(type) && type.isinterface()) { class<?> keytype = descriptor.getmapkeytype(); if (keytype == null || !string.class.isassignablefrom(keytype)) { if (descriptor.isrequired()) { throw new fatalbeanexception("key type [" + keytype + "] of map [" + type.getname() + "] must be assignable to [java.lang.string]"); } return null; } class<?> valuetype = descriptor.getmapvaluetype(); if (valuetype == null) { if (descriptor.isrequired()) { throw new fatalbeanexception("no value type declared for map [" + type.getname() + "]"); } return null; } map<string, object> matchingbeans = findautowirecandidates(beanname, valuetype, descriptor); if (matchingbeans.isempty()) { if (descriptor.isrequired()) { raisenosuchbeandefinitionexception(valuetype, "map with value type " + valuetype.getname(), descriptor); } return null; } if (autowiredbeannames != null) { autowiredbeannames.addall(matchingbeans.keyset()); } return matchingbeans; } else { map<string, object> matchingbeans = findautowirecandidates(beanname, type, descriptor); if (matchingbeans.isempty()) { if (descriptor.isrequired()) { raisenosuchbeandefinitionexception(type, "", descriptor); } return null; } if (matchingbeans.size() > 1) { string primarybeanname = determineprimarycandidate(matchingbeans, descriptor); if (primarybeanname == null) { throw new nouniquebeandefinitionexception(type, matchingbeans.keyset()); } if (autowiredbeannames != null) { autowiredbeannames.add(primarybeanname); } return matchingbeans.get(primarybeanname); } // we have exactly one match. map.entry<string, object> entry = matchingbeans.entryset().iterator().next(); if (autowiredbeannames != null) { autowiredbeannames.add(entry.getkey()); } //已经确定只有一个匹配项 return entry.getvalue(); } }
applypropertyvalues
程序运行到这里,已经完成了对所有注入属性的获取,但是获取的属性是以propertyvalues形式存在的,还并没有应用到已经实例化的bean中,这一工作是在applypropertyvalues中。继续跟踪到方法体中:
protected void applypropertyvalues(string beanname, beandefinition mbd, beanwrapper bw, propertyvalues pvs) { if (pvs == null || pvs.isempty()) { return; } mutablepropertyvalues mpvs = null; list<propertyvalue> original; if (system.getsecuritymanager() != null) { if (bw instanceof beanwrapperimpl) { ((beanwrapperimpl) bw).setsecuritycontext(getaccesscontrolcontext()); } } if (pvs instanceof mutablepropertyvalues) { mpvs = (mutablepropertyvalues) pvs; //如果mpvs中的值已经被转换为对应的类型那么可以直接设置到beanwapper中 if (mpvs.isconverted()) { // shortcut: use the pre-converted values as-is. try { bw.setpropertyvalues(mpvs); return; } catch (beansexception ex) { throw new beancreationexception( mbd.getresourcedescription(), beanname, "error setting property values", ex); } } original = mpvs.getpropertyvaluelist(); } else { //如果pvs并不是使用mutablepropertyvalues封装的类型,那么直接使用原始的属性获取方法 original = arrays.aslist(pvs.getpropertyvalues()); } typeconverter converter = getcustomtypeconverter(); if (converter == null) { converter = bw; } //获取对应的解析器 beandefinitionvalueresolver valueresolver = new beandefinitionvalueresolver(this, beanname, mbd, converter); // create a deep copy, resolving any references for values. list<propertyvalue> deepcopy = new arraylist<propertyvalue>(original.size()); boolean resolvenecessary = false; //遍历属性,将属性转换为对应类的对应属性的类型 for (propertyvalue pv : original) { if (pv.isconverted()) { deepcopy.add(pv); } else { string propertyname = pv.getname(); object originalvalue = pv.getvalue(); object resolvedvalue = valueresolver.resolvevalueifnecessary(pv, originalvalue); object convertedvalue = resolvedvalue; boolean convertible = bw.iswritableproperty(propertyname) && !propertyaccessorutils.isnestedorindexedproperty(propertyname); if (convertible) { convertedvalue = convertforproperty(resolvedvalue, propertyname, bw, converter); } // possibly store converted value in merged bean definition, // in order to avoid re-conversion for every created bean instance. if (resolvedvalue == originalvalue) { if (convertible) { pv.setconvertedvalue(convertedvalue); } deepcopy.add(pv); } else if (convertible && originalvalue instanceof typedstringvalue && !((typedstringvalue) originalvalue).isdynamic() && !(convertedvalue instanceof collection || objectutils.isarray(convertedvalue))) { pv.setconvertedvalue(convertedvalue); deepcopy.add(pv); } else { resolvenecessary = true; deepcopy.add(new propertyvalue(pv, convertedvalue)); } } } if (mpvs != null && !resolvenecessary) { mpvs.setconverted(); } // set our (possibly massaged) deep copy. try { bw.setpropertyvalues(new mutablepropertyvalues(deepcopy)); } catch (beansexception ex) { throw new beancreationexception( mbd.getresourcedescription(), beanname, "error setting property values", ex); } }
我们来看看具体的属性赋值过程
public class mytestbean { private string name ; public mytestbean(string name) { this.name = name; } public mytestbean() { } public string getname() { return name; } public void setname(string name) { this.name = name; } } <bean id="mytestbean" class="chenhao.spring01.mytestbean"> <property name="name" value="chenhao"></property> </bean>
如上 bw.setpropertyvalues 最终都会走到如下方法
@override public void setvalue(final @nullable object value) throws exception { //获取writemethod,也就是我们mytestbean的setname方法 final method writemethod = (this.pd instanceof generictypeawarepropertydescriptor ? ((generictypeawarepropertydescriptor) this.pd).getwritemethodforactualaccess() : this.pd.getwritemethod()); if (system.getsecuritymanager() != null) { accesscontroller.doprivileged((privilegedaction<object>) () -> { reflectionutils.makeaccessible(writemethod); return null; }); try { accesscontroller.doprivileged((privilegedexceptionaction<object>) () -> writemethod.invoke(getwrappedinstance(), value), acc); } catch (privilegedactionexception ex) { throw ex.getexception(); } } else { reflectionutils.makeaccessible(writemethod); //通过反射调用方法进行赋值 writemethod.invoke(getwrappedinstance(), value); } }
debug如下
就是利用反射进行调用对象的set方法赋值
至此,docreatebean()
第二个过程:属性填充 已经分析完成了,下篇分析第三个过程:循环依赖的处理,其实循环依赖并不仅仅只是在 docreatebean()
中处理,其实在整个加载 bean 的过程中都有涉及,所以下篇内容并不仅仅只局限于 docreatebean()
。
上一篇: 【转载】sqlserver中小数类型float和deciaml类型比较
下一篇: Mybaits 源码解析 (四)----- SqlSession的创建过程(看懂框架源码再也不用死记硬背面试题)
推荐阅读
-
spring源码深度解析— IOC 之 默认标签解析(上)
-
spring源码深度解析— IOC 之 循环依赖处理
-
spring源码深度解析— IOC 之 开启 bean 的加载
-
spring源码深度解析— IOC 之 默认标签解析(下)
-
spring源码深度解析— IOC 之 bean 的初始化
-
【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
-
【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
-
spring源码深度解析— IOC 之 属性填充
-
spring源码深度解析— IOC 之 默认标签解析(上)
-
spring源码深度解析— IOC 之 循环依赖处理