基于springboot2.1.4
1蒸甜、instantiateUsingFactoryMethod
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#instantiateUsingFactoryMethod-->org.springframework.beans.factory.support.ConstructorResolver#instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs)
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;
// 通過beanDefinition獲取到factoryBeanName 懂牧,實際就是@Bean注解的方法
//所在的configuration類
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
// 獲取configuration類的實例
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
factoryClass = factoryBean.getClass();
isStatic = false;
}
else {
// It's a static factory method on the bean class.
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
factoryBean = null;
factoryClass = mbd.getBeanClass();
isStatic = true;
}
Method factoryMethodToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
//如果在調(diào)用getBean方法時有傳參琢锋,那就用傳的參作為
//@Bean注解的方法(工廠方法)的參數(shù),
// 一般懶加載的bean才會傳參,啟動過程就實例化的實際上都沒有傳參
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
//不為空表示已經(jīng)使用過工廠方法赶熟,現(xiàn)在是再次使用工廠方法领猾,
// 一般原型模式和Scope模式采用的上米同,直接使用該工廠方法和緩存的參數(shù)
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached factory method...
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
}
}
// 調(diào)用getBean方法沒有傳參,同時也是第一次使用工廠方法
if (factoryMethodToUse == null || argsToUse == null) {
// Need to determine the factory method...
// Try all methods with this name to see if they match the given arguments.
factoryClass = ClassUtils.getUserClass(factoryClass);
// 獲取configuration類的所有候選方法
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
List<Method> candidateList = new ArrayList<>();
for (Method candidate : rawCandidates) {
// 查找到與工廠方法同名的候選方法,沒有@Bean的同名方法不被考慮
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidateList.add(candidate);
}
}
//當(dāng)與工廠方法同名的候選方法只有一個摔竿,且調(diào)用getBean方法時沒有傳參面粮,
// 且沒有緩存過參數(shù),直接通過調(diào)用實例化方法執(zhí)行該候選方法
if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidateList.get(0);
if (uniqueCandidate.getParameterCount() == 0) {
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
Method[] candidates = candidateList.toArray(new Method[0]);
// 有多個與工廠方法同名的候選方法時继低,進行排序熬苍。public的方法會往前排,然后參數(shù)個數(shù)多的方法往前排
//具體排序代碼--->org.springframework.beans.factory.support.AutowireUtils#sortConstructors
ConstructorArgumentValues resolvedValues = null;
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Method> ambiguousFactoryMethods = null;
int minNrOfArgs;
// 如果調(diào)用getBean方法時有傳參袁翁,那么工廠方法最少參數(shù)個數(shù)要等于傳參個數(shù)
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// We don't have arguments passed in programmatically, so we need to resolve the
// arguments specified in the constructor arguments held in the bean definition.
if (mbd.hasConstructorArgumentValues()) {
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
minNrOfArgs = 0;
}
}
LinkedList<UnsatisfiedDependencyException> causes = null;
// 遍歷同名候選方法
for (Method candidate : candidates) {
// 獲取候選方法的參數(shù)列表
Class<?>[] paramTypes = candidate.getParameterTypes();
if (paramTypes.length >= minNrOfArgs) {
ArgumentsHolder argsHolder;
//在調(diào)用getBean方法時傳的參數(shù)不為空柴底,則工廠方法的參數(shù)個數(shù)需要與
// 傳入的參數(shù)個數(shù)嚴格一致
if (explicitArgs != null) {
// Explicit arguments given -> arguments length must match exactly.
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
else {
// Resolved constructor arguments: type conversion and/or autowiring necessary.
try {
String[] paramNames = null;
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
//當(dāng)傳入的參數(shù)為空,需要根據(jù)工廠方法的參數(shù)類型注入相應(yīng)的
// bean梦裂。詳細的注入代碼可查看
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency
//暫不過多解析似枕,如有需要再另外開篇記錄
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next overloaded factory method.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
/**計算工廠方法的權(quán)重,分嚴格模式和寬松模式年柠,計算方式可以看本文最后的附錄
嚴格模式會校驗子類(注入?yún)?shù))繼承了多少層父類(方法參數(shù))層數(shù)越多權(quán)重越大凿歼,越不匹配
褪迟,寬松模式,只要是注入?yún)?shù)類型是方法參數(shù)類型的子類就行答憔。
默認寬松模式 在argsHolders中會有arguments和rawArguments味赃,;
例如在注入bean時虐拓,如果有經(jīng)歷過createArgumentArray方法中的TypeConverter
(如有有定義并且注冊到beanFactory中)的心俗,arguments和rawArguments的值是不一樣的
如果沒有經(jīng)過轉(zhuǎn)換,兩者是一樣的蓉驹。通過getBean傳入的參數(shù)兩者通常都是一樣的
所以都是先將工廠方法的參數(shù)類型與arguments的比較城榛,不同則賦予最大權(quán)重值,
相同則與rawArguments比較态兴,與rawArguments中的相同狠持,就會賦最大權(quán)重值-1024,
不相同瞻润,則賦最大權(quán)重值-512喘垂,經(jīng)過類型轉(zhuǎn)換一定會執(zhí)行最大權(quán)重值-512的操作。
權(quán)重值越大绍撞,該工廠方法越不匹配正勒。總的來說就是傳入的參數(shù)或者注入的參數(shù)類型
與工廠方法參數(shù)類型的比對傻铣。**/
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this factory method if it represents the closest match.
if (typeDiffWeight < minTypeDiffWeight) {
/** 當(dāng)權(quán)重小時章贞,重新設(shè)置factoryMethodToUse 和argsHolderToUse ,argsToUse 矾柜,
并把當(dāng)前權(quán)重值設(shè)置為最小權(quán)重值阱驾,等待遍歷的下一個候選工廠方法比對,
并且將ambiguousFactoryMethods (表示有含糊同樣權(quán)重的候選方法)設(shè)置為空**/
factoryMethodToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null;
}
// Find out about ambiguity: In case of the same type difference weight
// for methods with the same number of parameters, collect such candidates
// and eventually raise an ambiguity exception.
// However, only perform that check in non-lenient constructor resolution mode,
// and explicitly ignore overridden methods (with the same parameter signature).
/** 當(dāng)遍歷到下一個候選方法的時候怪蔑,已經(jīng)設(shè)置了factoryMethodToUse 且權(quán)重值
與上一次的最小權(quán)重值相等時里覆,ambiguousFactoryMethods填值,這個ambiguousFactoryMethods不為空
表示有兩個候選方法的最小權(quán)重相等缆瓣,spring無法匹配出最適合的工廠方法喧枷,
如果再繼續(xù)往下遍歷候選器,有更小的權(quán)重值弓坞,那ambiguousFactoryMethods會
再次被設(shè)置為空**/
else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
!mbd.isLenientConstructorResolution() &&
paramTypes.length == factoryMethodToUse.getParameterCount() &&
!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
if (ambiguousFactoryMethods == null) {
ambiguousFactoryMethods = new LinkedHashSet<>();
ambiguousFactoryMethods.add(factoryMethodToUse);
}
ambiguousFactoryMethods.add(candidate);
}
}
}
if (factoryMethodToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
List<String> argTypes = new ArrayList<>(minNrOfArgs);
if (explicitArgs != null) {
for (Object arg : explicitArgs) {
argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
}
}
else if (resolvedValues != null) {
Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
for (ValueHolder value : valueHolders) {
String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
argTypes.add(argType);
}
}
String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"No matching factory method found: " +
(mbd.getFactoryBeanName() != null ?
"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
"Check that a method with the specified name " +
(minNrOfArgs > 0 ? "and arguments " : "") +
"exists and that it is " +
(isStatic ? "static" : "non-static") + ".");
}
//返回類型不能為void
else if (void.class == factoryMethodToUse.getReturnType()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid factory method '" + mbd.getFactoryMethodName() +
"': needs to have a non-void return type!");
}
//存在含糊的兩個工廠方法隧甚,不知選哪個
else if (ambiguousFactoryMethods != null) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous factory method matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousFactoryMethods);
}
if (explicitArgs == null && argsHolderToUse != null) {
mbd.factoryMethodToIntrospect = factoryMethodToUse;
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
Assert.state(argsToUse != null, "Unresolved factory method arguments");
// 到達這里,恭喜渡冻,可以完成實例化了
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
}
看下例子
@Bean
public String getStr20(){
System.out.println("helloTest in HelloConfigurationInner20");
return "helloTest";
}
@Bean
public Executor getStr20(Executor executor){
System.out.println("helloTest in HelloConfigurationInner20");
return executor;
}
// 兩者參數(shù)個數(shù)一樣多戚扳,權(quán)重也一樣,兩者的參數(shù)都不是通過轉(zhuǎn)換類型得來的族吻,無法判斷哪個才是被選召的孩子
// @Bean
// public String getStr20(OrderBean hello){
// System.out.println("helloTest in HelloConfigurationInner20");
// return "helloTest"+hello;
// }
2帽借、autowireConstructor
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor--->org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs)
構(gòu)造器方法的過程有很多跟工廠方法相似的地方珠增,比如,傳入?yún)?shù)的處理砍艾,候選方法的排序蒂教,參數(shù)的注入,權(quán)重計算等梦皮。不同的是instantiateUsingFactoryMethod有factoryBean的查找覆旭,重要的邏輯基本差不多,就不重復(fù)記錄了七兜,重點說下在調(diào)用autowireConstructor前就要先獲取到構(gòu)造器腕铸,并作為參數(shù)傳入,重點來關(guān)注spring默認的獲取構(gòu)造方法的邏輯
進入org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance-->org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors遍歷所有的SmartInstantiationAwareBeanPostProcessor實例狠裹,執(zhí)行其determineCandidateConstructors方法(如有需要可以自定義SmartInstantiationAwareBeanPostProcessor撇吞,按需求重寫determineCandidateConstructors方法)默認的processor為AutowiredAnnotationBeanPostProcessor接著進入org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors看關(guān)鍵部分
//如果之前已經(jīng)有用構(gòu)造方法實例化bean,就會有緩存死姚,原型模式和scope模式會有再次使用的時候
// Quick check on the concurrent map first, with minimal locking.
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
// Fully synchronized resolution now...
synchronized (this.candidateConstructorsCache) {
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
Constructor<?>[] rawCandidates;
try {
//緩存中不存在的時候使用getDeclaredConstructors方法獲取所有的構(gòu)造方法
rawCandidates = beanClass.getDeclaredConstructors();
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
Constructor<?> requiredConstructor = null;
Constructor<?> defaultConstructor = null;
//優(yōu)先的構(gòu)造方法是從kotlin文件獲取,沒玩過kotlin,不知道怎么弄瀑焦,先不管
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
int nonSyntheticConstructors = 0;
for (Constructor<?> candidate : rawCandidates) {
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
else if (primaryConstructor != null) {
continue;
}
//查找是否有@Autowired注解
AnnotationAttributes ann = findAutowiredAnnotation(candidate);
if (ann == null) {
//如果沒有@Autowired注解,查找父類的構(gòu)造方法有沒有@Autowired注解
Class<?> userClass = ClassUtils.getUserClass(beanClass);
if (userClass != beanClass) {
try {
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
if (ann != null) {
// 當(dāng)@Autowired注解的構(gòu)造方法不止一個,那上一次處理的候選構(gòu)造方法
// 已經(jīng)設(shè)置到requiredConstructor 中粹懒,那么第二個@Autowired注解的
// 候選構(gòu)造方法處理的時候就會拋異常
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
boolean required = determineRequiredStatus(ann);
if (required) {
if (!candidates.isEmpty()) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found constructor with 'required' Autowired annotation: " +
candidate);
}
//第一個處理的有@autowired處理的構(gòu)造方法設(shè)置requiredConstructor 弓颈,并設(shè)置到candidates中
requiredConstructor = candidate;
}
candidates.add(candidate);
}
//當(dāng)構(gòu)造方法沒有@Autowired注解且參數(shù)個數(shù)為0橘蜜,選為defaultConstructor
else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
}
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
if (requiredConstructor == null) {
if (defaultConstructor != null) {
//往候選方法中加入defaultConstructor
//(好像requiredConstructor 為null象颖,candidates就會為null潮瓶,感覺此句永遠不會執(zhí)行)
candidates.add(defaultConstructor);
}
else if (candidates.size() == 1 && logger.isInfoEnabled()) {
logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
"': single autowire-marked constructor flagged as optional - " +
"this constructor is effectively required since there is no " +
"default constructor to fall back to: " + candidates.get(0));
}
}
//候選方法不為空的時候進入此處,此時就一個@Autowired注解的構(gòu)造方法
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//當(dāng)獲取的所有構(gòu)造方法只有一個思恐,且不是@autowired注解的(注解的在上面處理了)
//且參數(shù)在一個以上栅螟,該方法作為候選的構(gòu)造方法
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//后面primaryConstructor 的都不看了
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
else {
candidateConstructors = new Constructor<?>[0];
}
//緩存選定的候選構(gòu)造方法搪哪,供原型模式和scope模式第二次實例化時使用
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
返回選定的構(gòu)造函數(shù)列表
return (candidateConstructors.length > 0 ? candidateConstructors : null);
上demo
/**首先永遠不必理會無參構(gòu)造方法,他最后都是不會通過autowireConstructor方法實例化坪圾,
如果只有一個帶參構(gòu)造方法晓折,那他就被選擇為候選構(gòu)造方法,如果有多個帶參構(gòu)造方法兽泄,
則需要通過@Autowired注解其中一個漓概,不能有多個@Autowired注解的構(gòu)造方法**/
// public TestService(){}
// @Autowired
public TestService(OrderBean orderBean) {
this.orderBean = orderBean;
}
// @Autowired
// public TestService(Executor executor,OrderBean orderBean){}
附