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

spring源码深度解析— IOC 之 属性填充

程序员文章站 2022-03-20 17:14:48
doCreateBean() 主要用于完成 bean 的创建和初始化工作,我们可以将其分为四个过程: createBeanInstance() 实例化 bean populateBean() 属性填充 循环依赖的处理 initializeBean() 初始化 bean 第一个过程实例化 bean在前 ......

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如下

spring源码深度解析— IOC 之 属性填充

就是利用反射进行调用对象的set方法赋值

至此,docreatebean() 第二个过程:属性填充 已经分析完成了,下篇分析第三个过程:循环依赖的处理,其实循环依赖并不仅仅只是在 docreatebean() 中处理,其实在整个加载 bean 的过程中都有涉及,所以下篇内容并不仅仅只局限于 docreatebean()