前文提到在createBeanInstance中实例化Bean一共有四种方式:Supplier回调:obtainFromSupplier()工厂方法初始化:instantiateUsingFactoryMethod()构造函数自动注入初始化:autowireConstructor()默认构造函数注入:instantiateBean() 这篇就来分析两种方式。还是在AbstractAutowireCapableBeanFactory。createBeanInstance方法中。上述代码省略booleanresolvedfalse;booleanautowireNecessaryfalse;调用getBean()时不传入参数if(argsnull){synchronized(mbd。constructorArgumentLock)当作用域为原型时、多次调用getBean()时不传入参数,从缓存中获取这段逻辑才会被执行resolvedConstructorOrFactoryMethod缓存了已解析的构造函数或工厂方法if(mbd。resolvedConstructorOrFactoryMethod!null){resolved为true,表示当前bean的构造方法已经确定了,也代表该Bean之前被解析过resolvedtrue;constructorArgumentsResolved:将构造函数参数标记为已解析true就是标记为了已解析默认为false。如果autowireNecessary为true说明是采用有参构造函数注入autowireNecessarymbd。constructorArgumentsResolved;}}}resolvedtrue,表示当前bean的构造方法已经确定了if(resolved){autowireNecessarytrue,表示采用有参构造函数注入if(autowireNecessary){采用有参构造函数注入returnautowireConstructor(beanName,mbd,null,null);}else{构造方法已经确定了,但是没有确定构造方法参数那就表示没有构造方法参数,用无参的构造方法来实例化beanreturninstantiateBean(beanName,mbd);}} 上面这段代码的逻辑为:如果没有显示的传入参数,判断resolvedConstructorOrFactoryMethod是否不为空,如果不为空,则存在缓存,直接使用已经解析了的构造函数。然后根据autowireNecessary参数来判断是使用有参构造函数自动注入还是使用无参构造函数注入。autowireConstructor 先来看一下autowireConstructor方法,也就是有参构造函数自动注入。进入ConstructorResolver类的autowireConstructor方法。该方法有四个参数:beanName:当前Bean的名称。mbd:当前Bean的定义。chosenCtors:经过筛选的构造方法列表。可能为null。explicitArgs:开发者在调用getBean方法时显示传递的参数。publicBeanWrapperautowireConstructor(StringbeanName,RootBeanDefinitionmbd,NullableConstructorlt;?〔〕chosenCtors,NullableObject〔〕explicitArgs){BeanWrapperImplbwnewBeanWrapperImpl();this。beanFactory。initBeanWrapper(bw);最终需要使用的构造方法变量Constructorlt;?constructorToUsenull;ArgumentsHolderargsHolderToUsenull;最终需要使用的参数变量Object〔〕argsToUsenull;getBean()方法指定了构造方法参数if(explicitArgs!null){argsToUseexplicitArgs;}else{从缓存中获取构造方法和构造方法参数当作用域为原型时并多次调用getBean()时没有传递参数创建Bean是会走这段缓存逻辑。为单例只会从一次,之后的getBean()都会从单例池获取。Object〔〕argsToResolvenull;synchronized(mbd。constructorArgumentLock){resolvedConstructorOrFactoryMethod:缓存已解析的构造函数或工厂方法constructorToUse(Constructorlt;?)mbd。resolvedConstructorOrFactoryMethod;找到了mbd中缓存的构造方法constructorArgumentsResolved:将构造函数参数标记为已解析true就是标记为了已解析if(constructorToUse!nullmbd。constructorArgumentsResolved){resolvedConstructorArguments:获得已完全解析的构造函数参数(参数类型已经确定,能够直接进行使用)正常情况下resolvedConstructorArguments的值就是nullargsToUsembd。resolvedConstructorArguments;if(argsToUsenull){获得部分准备好的构造函数参数(该参数的类型是不确定的,需要进行解析)argsToResolvembd。preparedConstructorArguments;}}}如果存在构造函数参数,那么则对参数值进行类型转化如给定方法的构造函数Person(int)则通过此方法后就会把配置中的5转换为5constructorargindex0value5缓存中的值可能是原始值也可能是最终值if(argsToResolve!null){argsToUseresolvePreparedArguments(beanName,mbd,bw,constructorToUse,argsToResolve,true);}}如果待使用的构造方法为null,或待使用的构造方法参数为null,也就是没有缓存这个if代码很长,但其实就去找构造方法、构造方法参数并赋值给constructorToUse、argsToUseif(constructorToUsenullargsToUsenull){chosenCtors表示所指定的构造方法没有指定则获取beanClass中的所有的构造方法作为候选者从这些构造方法中选择一个构造方法Constructorlt;?〔〕candidateschosenCtors;if(candidatesnull){Classlt;?beanClassmbd。getBeanClass();try{mbd。isNonPublicAccessAllowed():默认为truegetDeclaredConstructors():获得本类所有构造方法getConstructors:获得本类的所有公有构造方法candidates(mbd。isNonPublicAccessAllowed()?beanClass。getDeclaredConstructors():beanClass。getConstructors());}catch(Throwableex){thrownewBeanCreationException(mbd。getResourceDescription(),beanName,ResolutionofdeclaredconstructorsonbeanClass〔beanClass。getName()〕fromClassLoader〔beanClass。getClassLoader()〕failed,ex);}}如果只有一个构造方法,并且没有显示指定构造方法参数并且在xml中没有使用constructorarg标签则需要判断是不是无参构造方法,如果是则使用无参构造方法进行实例化if(candidates。length1explicitArgsnull!mbd。hasConstructorArgumentValues()){Constructorlt;?uniqueCandidatecandidates〔0〕;判断是不是无参构造方法if(uniqueCandidate。getParameterCount()0){synchronized(mbd。constructorArgumentLock){确定了构造方法之后进行缓存mbd。resolvedConstructorOrFactoryMethoduniqueCandidate;mbd。constructorArgumentsResolvedtrue;mbd。resolvedConstructorArgumentsEMPTYARGS;}进行实例化bw。setBeanInstance(instantiate(beanName,mbd,uniqueCandidate,EMPTYARGS));returnbw;}}如果入参chosenCtors不为null,也就是找到了构造方法,或者autowireMode是构造方法自动注入则可能要自动选择构造方法booleanautowiring(chosenCtors!nullmbd。getResolvedAutowireMode()AutowireCapableBeanFactory。AUTOWIRECONSTRUCTOR);记录解析后的构造方法参数值ConstructorArgumentValuesresolvedValuesnull;minNrOfArgs:表示所有构造方法中,参数个数最少的构造方法的参数个数是多少intminNrOfArgs;if(explicitArgs!null){minNrOfArgsexplicitArgs。length;}else{从BeanDefinition中获取所设置的构造方法参数值值来源于constructorarg标签中的index属性的值这个值可以随便写ConstructorArgumentValuescargsmbd。getConstructorArgumentValues();记录解析后的构造方法参数值resolvedValuesnewConstructorArgumentValues();解析参数个数值来源于constructorarg标签中的index属性的值这个值可以随便写minNrOfArgsresolveConstructorArguments(beanName,mbd,bw,cargs,resolvedValues);}按构造方法的参数个数降序排序,先排序public构造函数,参数降序排列然后排序非public的构造函数,参数降序排列AutowireUtils。sortConstructors(candidates);intminTypeDiffWeightInteger。MAXVALUE;SetConstructorlt;?ambiguousConstructorsnull;LinkedListUnsatisfiedDependencyExceptioncausesnull;遍历构造方法,找到一个最合适的先看参数列表最长的构造方法,根据每个参数的参数类型和参数名去找beanfor(Constructorlt;?candidate:candidates){当前构造方法的参数个数intparameterCountcandidate。getParameterCount();已经找到选用的构造函数且该参数个数大于当前遍历的,则不用继续遍历了上面已经按照参数个数降序排列了if(constructorToUse!nullargsToUse!nullargsToUse。lengthparameterCount){break;}在遍历某个构造方法时,如果当前遍历的参数个数小于所指定的参数个数则忽略该构造方法minNrOfArgs已经是最小的了,比他还小肯定是不符合我所需要的,就不必往下执行了if(parameterCountminNrOfArgs){continue;}ArgumentsHolderargsHolder;当前遍历到的构造方法的参数类型Classlt;?〔〕paramTypescandidate。getParameterTypes();当getBean()方法没有显示指定构造方法参数,resolvedValues不为nullif(resolvedValues!null){try{获取参数名查看是否在构造方法上使用ConstructorProperties注解来定义构造方法参数的名字String〔〕paramNamesConstructorPropertiesChecker。evaluate(candidate,parameterCount);if(paramNamesnull){ParameterNameDiscoverer用于解析方法、构造函数上的参数名称ParameterNameDiscovererpndthis。beanFactory。getParameterNameDiscoverer();if(pnd!null){获取构造函数的参数名称paramNamespnd。getParameterNames(candidate);}}根据当前构造方法的参数类型和参数名从beanFactory中得到bean作为参数值resolvedValues:解析后的构造方法参数值paramTypes:当前构造方法中每个参数的属性类型paramNames:当前构造方法中每个参数的属性名称getUserDeclaredConstructor(candidate):获取父类中被重写的构造方法argsHoldercreateArgumentArray(beanName,mbd,resolvedValues,bw,paramTypes,paramNames,getUserDeclaredConstructor(candidate),autowiring,candidates。length1);}catch(UnsatisfiedDependencyExceptionex){如果找不到相匹配的,也不会直接报错只能说明当前遍历的构造方法不能用if(logger。isTraceEnabled()){logger。trace(Ignoringconstructor〔candidate〕ofbeanbeanName:ex);}Swallowandtrynextconstructor。if(causesnull){causesnewLinkedList();}causes。add(ex);continue;}}else{getBean()方法指定了构造方法参数值当前构造方法参数个数与传入的参数个数不相等,跳出本次循环if(parameterCount!explicitArgs。length){continue;}如果参数个数匹配,则把所有参数值封装为一个ArgumentsHolder对象argsHoldernewArgumentsHolder(explicitArgs);}执行到这里,表示当前构造方法可用,并且也找到了对应的构造方法参数值但是还需要判断,当前构造方法是不是最合适的,也许还有另外的构造方法更合适根据参数类型和参数值计算权重Lenient宽松,默认宽松模式是开启的严格模式:解析构造函数时,必须所有的都需要匹配,否则抛出异常宽松模式:使用具有最接近的模式进行匹配inttypeDiffWeight(mbd。isLenientConstructorResolution()?argsHolder。getTypeDifferenceWeight(paramTypes):argsHolder。getAssignabilityWeight(paramTypes));Choosethisconstructorifitrepresentstheclosestmatch。如果当前构造方法的权重比较小,则表示当前构造方法更合适将当前构造方法和所找到参数值作为待使用的遍历下一个构造方法if(typeDiffWeightminTypeDiffWeight){constructorToUsecandidate;argsHolderToUseargsHolder;argsToUseargsHolder。arguments;minTypeDiffWeighttypeDiffWeight;ambiguousConstructorsnull;}elseif(constructorToUse!nulltypeDiffWeightminTypeDiffWeight){如果权重一样,则记录在ambiguousConstructors中,继续遍历下一个构造方法if(ambiguousConstructorsnull){ambiguousConstructorsnewLinkedHashSet();ambiguousConstructors。add(constructorToUse);}ambiguousConstructors。add(candidate);}循环结束}遍历完所有构造方法后,没有找到合适的构造方法,则报错if(constructorToUsenull){if(causes!null){UnsatisfiedDependencyExceptionexcauses。removeLast();for(Exceptioncause:causes){this。beanFactory。onSuppressedException(cause);}throwex;}thrownewBeanCreationException(mbd。getResourceDescription(),beanName,Couldnotresolvematchingconstructor(hint:specifyindextypenameargumentsforsimpleparameterstoavoidtypeambiguities));}如果存在权重一样的构造方法并且不是宽松模式,也报错因为权重一样,Spring不知道该用哪个如果是宽松模式则不会报错,Spring会用找到的第一个elseif(ambiguousConstructors!null!mbd。isLenientConstructorResolution()){thrownewBeanCreationException(mbd。getResourceDescription(),beanName,AmbiguousconstructormatchesfoundinbeanbeanName(hint:specifyindextypenameargumentsforsimpleparameterstoavoidtypeambiguities):ambiguousConstructors);}如果不是通过getBean()方法指定的参数,那么就把找到的构造方法参数进行缓存if(explicitArgsnullargsHolderToUse!null){缓存找到的构造方法argsHolderToUse。storeCache(mbd,constructorToUse);}}得到了构造方法和构造方法的参数值之后,就可以进行实例化了Assert。state(argsToUse!null,Unresolvedconstructorarguments);bw。setBeanInstance(instantiate(beanName,mbd,constructorToUse,argsToUse));returnbw;} 代码很长,但总体来说就是确定一件事情。确定构造函数、构造函数参数,然后调用instantiate方法进行bean的实例化。 总体思路:先检查是否指定了具体的构造方法和构造方法参数值,或者在BeanDefinition中缓存了具体的构造方法或构造方法参数值,如果存在那么则直接使用该构造方法进行实例化。如果没有确定的构造方法或构造方法参数值,又分为以下流程:a。如果没有确定构造方法,那么则找出类中所有的构造方法。b。如果只有一个无参的构造方法,那么直接使用无参的构造方法进行实例化。c。如果有多个构造方法或者当前Bean的注入方式是构造方法自动注入,则要自动选择构造方法。d。根据所指定的构造方法参数值,确定所需要的最少的构造方法参数值的个数。如果没有指定,从BeanDefinition的constructorArgumentValues属性获取。e。对所有的构造方法进行排序,public构造函数优先参数数量降序,非public构造函数参数数量降序。f。遍历每个构造方法。g。如果调用getBean方法时,没有显示指定构造方法参数值,那么则根据当前循环到的构造方法得到构造参数类型、构造参数名称与解析后的构造方法参数值(resolvedValues)进行匹配,构建ArgumentsHolder对象。h。如果调用getBean方法时,指定构造方法参数值,就直接利用传入的构造方法参数值构建ArgumentsHolder对象。i。如果根据当前构造方法找到了对应的构造方法参数值,那么这个构造方法就是可用的,但是不一定这个构造方法就是最佳的,所以这里会涉及到是否有多个构造方法匹配了同样的值,这个时候就会用值和构造方法类型进行匹配程度的打分,找到一个最匹配的(分越少优先级越高)。为什么分越少优先级越高? 主要是计算找到的bean和构造方法参数类型匹配程度有多高 假设bean的类型为A,A的父类是B,B的父类是C,同时A实现了接口D如果构造方法的参数类型为A,那么完全匹配,得分为0如果构造方法的参数类型为B,那么得分为2如果构造方法的参数类型为C,那么得分为4如果构造方法的参数类型为D,那么得分为1 可以直接使用如下代码进行测试:Object〔〕objectsnewObject〔〕{newA()};0System。out。println(MethodInvoker。getTypeDifferenceWeight(newClass〔〕{A。class},objects));2System。out。println(MethodInvoker。getTypeDifferenceWeight(newClass〔〕{B。class},objects));4System。out。println(MethodInvoker。getTypeDifferenceWeight(newClass〔〕{C。class},objects));1System。out。println(MethodInvoker。getTypeDifferenceWeight(newClass〔〕{D。class},objects));举例 各位小伙伴可以下去跑一下例子,打打断点。举例一、1、创建A、B类,其中A类有B属性、name属性。并且在A(Bb)这个构造方法加上Autowired注解,表示要使用这个构造方法实例化对象。publicclassA{privateBb;privateStringname;publicA(){}AutowiredpublicA(Bb){this。bb;}publicA(Stringname){this。namename;}publicA(Bb,Stringname){this。bb;this。namename;}publicBgetB(){returnb;}publicvoidsetB(Bb){this。bb;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this。namename;}OverridepublicStringtoString(){returnA{bb,namename};}}publicclassB{}2、springconfig4。xmllt;?xmlversion1。0encodingUTF8?beansxmlnshttp:www。springframework。orgschemabeansxmlns:xsihttp:www。w3。org2001XMLSchemainstancexmlns:contexthttp:www。springframework。orgschemacontextxsi:schemaLocationhttp:www。springframework。orgschemabeanshttp:www。springframework。orgschemabeansspringbeans。xsdhttp:www。springframework。orgschemacontexthttps:www。springframework。orgschemacontextspringcontext。xsdbeanclasscom。gongj。create。Aidaabeanbeanclasscom。gongj。create。Bidbbbeancontext:componentscanbasepackagecom。gongj。createcontext:componentscanbeans3、启动publicstaticvoidmain(String〔〕args){ClassPathXmlApplicationContextcontextnewClassPathXmlApplicationContext(springconfig4。xml);Aa(A)context。getBean(aa);System。out。println(a);}结果:A{bcom。gongj。create。B27808f31,namenull}举例二、1、修改springconfig4。xml配置内容lt;?xmlversion1。0encodingUTF8?beansxmlnshttp:www。springframework。orgschemabeansxmlns:xsihttp:www。w3。org2001XMLSchemainstancexmlns:contexthttp:www。springframework。orgschemacontextxsi:schemaLocationhttp:www。springframework。orgschemabeanshttp:www。springframework。orgschemabeansspringbeans。xsdhttp:www。springframework。orgschemacontexthttps:www。springframework。orgschemacontextspringcontext。xsd!这里使用constructorargbeanclasscom。gongj。create。Aidaaconstructorargindex1valuegongjconstructorargconstructorargindex0refbbconstructorargbeanbeanclasscom。gongj。create。Bidbbbeancontext:componentscanbasepackagecom。gongj。createcontext:componentscanbeans2、启动publicstaticvoidmain(String〔〕args){ClassPathXmlApplicationContextcontextnewClassPathXmlApplicationContext(springconfig4。xml);Aa(A)context。getBean(aa);System。out。println(a);} 各位可以猜猜运行结果是什么?结果是报错! 那小杰将Autowired注解标注在A(Bb,Stringname)构造方法上,结果又是如何?AutowiredpublicA(Bb,Stringname){this。bb;this。namename;}结果:A{bcom。gongj。create。B3e57cd70,namegongj}举例三、1、将A的作用域修改为prototype。beanclasscom。gongj。create。Aidaascopeprototypeconstructorargindex0refbbconstructorargconstructorargindex1valuegongjconstructorargbean2、启动publicstaticvoidmain(String〔〕args){ClassPathXmlApplicationContextcontextnewClassPathXmlApplicationContext(springconfig4。xml);Aa(A)context。getBean(aa);System。out。println(aa。hashCode());Aa2(A)context。getBean(aa,newB(),uanjfjef);System。out。println(a2a2。hashCode());Aa3(A)context。getBean(aa);System。out。println(a3a3。hashCode());}结果:A{bcom。gongj。create。B3e57cd70,namegongj}161960012用了传入的值A{bcom。gongj。create。B2c039ac6,nameuanjfjef}1484594489用了缓存的值,而且并没有缓存传入的值A{bcom。gongj。create。B3e57cd70,namegongj}1489069835 其中有几个方法简单的提一下:resolveConstructorArguments 解析构造方法的参数值。可能会创建Bean。比如上述举例二。privateintresolveConstructorArguments(StringbeanName,RootBeanDefinitionmbd,BeanWrapperbw,ConstructorArgumentValuescargs,ConstructorArgumentValuesresolvedValues){获得当前beanFatory类型转换器TypeConvertercustomConverterthis。beanFactory。getCustomTypeConverter();获得当前beanFatory类型转换器为null,则使用bw,bw实现了TypeConverterTypeConverterconverter(customConverter!null?customConverter:bw);为给定的BeanFactory和BeanDefinition创建一个BeanDefinitionValueResolverBeanDefinitionValueResolvervalueResolvernewBeanDefinitionValueResolver(this。beanFactory,beanName,mbd,converter);获得constructorarg标签的个数intminNrOfArgscargs。getArgumentCount();先遍历cargs中的indexedArgumentValuesindexedArgumentValues存的是某个index对应的构造方法参数值for(Map。EntryInteger,ConstructorArgumentValues。ValueHolderentry:cargs。getIndexedArgumentValues()。entrySet()){intindexentry。getKey();if(index0){thrownewBeanCreationException(mbd。getResourceDescription(),beanName,Invalidconstructorargumentindex:index);}if(indexminNrOfArgs){minNrOfArgsindex1;}获得构造方法参数值ConstructorArgumentValues。ValueHoldervalueHolderentry。getValue();if(valueHolder。isConverted()){把该数据添加到resolvedValues对象中resolvedValues。addIndexedArgumentValue(index,valueHolder);}else{把值转化为对应的类型获得constructorarg的valueresolveValueIfNecessary:这里可能会创建bean因为constructorarg里面有个ref属性可以引用其他bean。ObjectresolvedValuevalueResolver。resolveValueIfNecessary(constructorargument,valueHolder。getValue());ConstructorArgumentValues。ValueHolderresolvedValueHoldernewConstructorArgumentValues。ValueHolder(resolvedValue,valueHolder。getType(),valueHolder。getName());resolvedValueHolder。setSource(valueHolder);把该数据添加到resolvedValues对象中resolvedValues。addIndexedArgumentValue(index,resolvedValueHolder);}}for循环结束把genericArgumentValues中的值进行类型转化然后添加到resolvedValues中去根据上述循环逻辑差不多for(ConstructorArgumentValues。ValueHoldervalueHolder:cargs。getGenericArgumentValues()){if(valueHolder。isConverted()){resolvedValues。addGenericArgumentValue(valueHolder);}else{ObjectresolvedValuevalueResolver。resolveValueIfNecessary(constructorargument,valueHolder。getValue());ConstructorArgumentValues。ValueHolderresolvedValueHoldernewConstructorArgumentValues。ValueHolder(resolvedValue,valueHolder。getType(),valueHolder。getName());resolvedValueHolder。setSource(valueHolder);resolvedValues。addGenericArgumentValue(resolvedValueHolder);}}for循环结束returnminNrOfArgs;} 首先获得当前Bean的constructorarg标签的个数minNrOfArgs,然后遍历cargs中的indexedArgumentValues元素,获取每个对象的key(也就是constructorarg标签的index元素),与minNrOfArgs进行比较。顺便将key和value添加到resolvedValues对象中。createArgumentArray 构造参数持有者。拥有最终要使用的构造参数。privateArgumentsHoldercreateArgumentArray(StringbeanName,RootBeanDefinitionmbd,NullableConstructorArgumentValuesresolvedValues,BeanWrapperbw,Classlt;?〔〕paramTypes,NullableString〔〕paramNames,Executableexecutable,booleanautowiring,booleanfallback)throwsUnsatisfiedDependencyException{TypeConvertercustomConverterthis。beanFactory。getCustomTypeConverter();TypeConverterconverter(customConverter!null?customConverter:bw);根据参数类型的个数初始化出来对应的ArgumentsHolderArgumentsHolderargsnewArgumentsHolder(paramTypes。length);SetConstructorArgumentValues。ValueHolderusedValueHoldersnewHashSet(paramTypes。length);SetStringautowiredBeanNamesnewLinkedHashSet(4);循环执行for(intparamIndex0;paramIndexparamTypes。length;paramIndex){获得参数类型Classlt;?paramTypeparamTypes〔paramIndex〕;获得参数名称StringparamName(paramNames!null?paramNames〔paramIndex〕:);Trytofindmatchingconstructorargumentvalue,eitherindexedorgeneric。尝试查找匹配的构造函数参数值,无论是索引的还是通用的ConstructorArgumentValues。ValueHoldervalueHoldernull;如果指定了构造方法参数值,那么则看当前paramType有没有对应的值if(resolvedValues!null){拿到第paramIndex位置的构造方法参数值,会根据传进去的类型、名称进行匹配如果类型、名称不相等则返回nullvalueHolderresolvedValues。getArgumentValue(paramIndex,paramType,paramName,usedValueHolders);如果找不到直接匹配项,尝试一个通用的,无类型的参数值作为后备,类型转换后可以匹配(例如,Stringint)。if(valueHoldernull(!autowiringparamTypes。lengthresolvedValues。getArgumentCount())){valueHolderresolvedValues。getGenericArgumentValue(null,null,usedValueHolders);}}如果找到了对应的值,则进行类型转化,把转化前的值存在args。rawArguments中转化后的值存在args。arguments中if(valueHolder!null){usedValueHolders。add(valueHolder);ObjectoriginalValuevalueHolder。getValue();ObjectconvertedValue;if(valueHolder。isConverted()){convertedValuevalueHolder。getConvertedValue();args。preparedArguments〔paramIndex〕convertedValue;}else{为给定的方法或构造函数创建一个新的MethodParameter。MethodParametermethodParamMethodParameter。forExecutable(executable,paramIndex);try{进行类型转换convertedValueconverter。convertIfNecessary(originalValue,paramType,methodParam);}catch(TypeMismatchExceptionex){thrownewUnsatisfiedDependencyException(mbd。getResourceDescription(),beanName,newInjectionPoint(methodParam),Couldnotconvertargumentvalueoftype〔ObjectUtils。nullSafeClassName(valueHolder。getValue())〕torequiredtype〔paramType。getName()〕:ex。getMessage());}ObjectsourceHoldervalueHolder。getSource();if(sourceHolderinstanceofConstructorArgumentValues。ValueHolder){ObjectsourceValue((ConstructorArgumentValues。ValueHolder)sourceHolder)。getValue();将resolveNecessary变量赋值为true,该变量会影响resolvedConstructorArguments:缓存完全解析的构造函数参数preparedConstructorArguments:缓存部分准备好的构造函数参数这两个参数是谁为null值args。resolveNecessarytrue;args。preparedArguments〔paramIndex〕sourceValue;}}args。arguments〔paramIndex〕convertedValue;args。rawArguments〔paramIndex〕originalValue;}else{如果上述逻辑,没有找到对应的值。举例中的举例一就会走该代码分支为给定的方法或构造函数创建一个新的MethodParameter。MethodParametermethodParamMethodParameter。forExecutable(executable,paramIndex);if(!autowiring){thrownewUnsatisfiedDependencyException(mbd。getResourceDescription(),beanName,newInjectionPoint(methodParam),Ambiguousargumentvaluesforparameteroftype〔paramType。getName()〕didyouspecifythecorrectbeanreferencesasarguments?);}如果autowiring的值为true,也就是如果入参chosenCtors不为null,也就是找到了构造方法或者autowireMode是构造方法自动注入,则可能要自动选择构造方法booleanautowiring(chosenCtors!nullmbd。getResolvedAutowireMode()AutowireCapableBeanFactory。AUTOWIRECONSTRUCTOR);try{该方法内部会调用resolveDependency方法,得到一个bean,resolveDependency方法很重要。ObjectautowiredArgumentresolveAutowiredArgument(methodParam,beanName,autowiredBeanNames,converter,fallback);args。rawArguments〔paramIndex〕autowiredArgument;args。arguments〔paramIndex〕autowiredArgument;args。preparedArguments〔paramIndex〕autowiredArgumentMarker;将resolveNecessary变量赋值为true,该变量会影响resolvedConstructorArguments:缓存完全解析的构造函数参数preparedConstructorArguments:缓存部分准备好的构造函数参数这两个参数是否为nullargs。resolveNecessarytrue;}catch(BeansExceptionex){thrownewUnsatisfiedDependencyException(mbd。getResourceDescription(),beanName,newInjectionPoint(methodParam),ex);}}}for(StringautowiredBeanName:autowiredBeanNames){this。beanFactory。registerDependentBean(autowiredBeanName,beanName);if(logger。isDebugEnabled()){logger。debug(AutowiringbytypefrombeannamebeanNamevia(executableinstanceofConstructor?constructor:factorymethod)tobeannamedautowiredBeanName);}}最后,返回找到的值returnargs;} 根据当前构造方法的参数类型、参数名称与上面解析得到的构造方法参数值进行匹配,如果匹配成功返回构造方法的参数值,进行类型转换。然后将必要的属性进行赋值,最后进行返回。instantiate instantiate方法,该方法在SimpleInstantiationStrategy类中实现。OverridepublicObjectinstantiate(RootBeanDefinitionbd,NullableStringbeanName,BeanFactoryowner,finalConstructorlt;?ctor,Object。。。args){bd。hasMethodOverrides():是否为此bean定义了方法重写,方法返回true说明重写了if(!bd。hasMethodOverrides()){没有重写,直接使用反射实例化即可if(System。getSecurityManager()!null){useownprivilegedtochangeaccessibility(whensecurityison)AccessController。doPrivileged((PrivilegedActionObject)(){ReflectionUtils。makeAccessible(ctor);returnnull;});}通过BeanUtils直接使用构造器对象实例化beanreturnBeanUtils。instantiateClass(ctor,args);}else{重写了生成CGLIB创建的子类对象returninstantiateWithMethodInjection(bd,beanName,owner,ctor,args);}} 如果该Bean没有配置lookupmethod、replacedmethod标签或者Lookup注解,则直接通过反射的方式实例化Bean。如果配置了则需要使用CGLIB进行动态代理。instantiateBean 使用无参的构造方法来实例化bean。protectedBeanWrapperinstantiateBean(finalStringbeanName,finalRootBeanDefinitionmbd){try{ObjectbeanInstance;finalBeanFactoryparentthis;if(System。getSecurityManager()!null){beanInstanceAccessController。doPrivileged((PrivilegedActionObject)()getInstantiationStrategy()。instantiate(mbd,beanName,parent),getAccessControlContext());}else{beanInstancegetInstantiationStrategy()。instantiate(mbd,beanName,parent);}BeanWrapperbwnewBeanWrapperImpl(beanInstance);initBeanWrapper(bw);returnbw;}catch(Throwableex){thrownewBeanCreationException(mbd。getResourceDescription(),beanName,Instantiationofbeanfailed,ex);}} instantiateBean方法相比于instantiateUsingFactoryMethod、autowireConstructor方法实在是太简单了,因为它没有参数,所以不需要确定构造方法、构造方法参数,直接调用实例化策略进行实例化就可以了。 作者:程序员小杰 链接:https:juejin。cnpost7005388320016433165