【spring源码分析】IOC容器初始化(九)

前言:上篇文章末尾提到createBeanInstance方法中使用工厂方法实例化Bean对象,本文将对该方法进行分析。


AbstractAutowireCapableBeanFactory#instantiateUsingFactoryMethod

1     protected BeanWrapper instantiateUsingFactoryMethod(
2             String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
3 
4         return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
5     }

可以看到这里是委托给ConstructorResolver来实现的:

  1 // ConstructorResolver
  2 public BeanWrapper instantiateUsingFactoryMethod(
  3             String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
  4         // 构造BeanWrapperImpl对象
  5         BeanWrapperImpl bw = new BeanWrapperImpl();
  6         // 初始化BeanWrapperImpl 向BeanWrapper对象中添加ConversionService对象和属性编辑器PropertyEditor对象
  7         this.beanFactory.initBeanWrapper(bw);
  8 
  9         // 获得factoryBean、factoryClass、isStatic、factoryBeanName属性
 10         Object factoryBean;
 11         Class<?> factoryClass;
 12         boolean isStatic;
 13 
 14         String factoryBeanName = mbd.getFactoryBeanName();
 15         // 工厂名不为空
 16         if (factoryBeanName != null) {
 17             // 如果工厂名和beanName相等,则抛出BeanDefinitionStoreException异常
 18             if (factoryBeanName.equals(beanName)) {
 19                 throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
 20                                                        "factory-bean reference points back to the same bean definition");
 21             }
 22             // 获取工厂实例
 23             factoryBean = this.beanFactory.getBean(factoryBeanName);
 24             // 如果是单例模式,并且已经缓存中已经存在beanName则抛出异常
 25             if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
 26                 throw new ImplicitlyAppearedSingletonException();
 27             }
 28             factoryClass = factoryBean.getClass();
 29             isStatic = false;
 30         } else {
 31             // 工厂名为空,则其可能是一个静态工厂
 32             // 静态工厂创建bean,必须要提供工厂的全类名
 33             // It's a static factory method on the bean class.
 34             if (!mbd.hasBeanClass()) {
 35                 throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
 36                                                        "bean definition declares neither a bean class nor a factory-bean reference");
 37             }
 38             factoryBean = null;
 39             factoryClass = mbd.getBeanClass();
 40             isStatic = true;
 41         }
 42 
 43         // 获得factoryMethodToUse、argsHolderToUse、argsToUse属性
 44         Method factoryMethodToUse = null;
 45         ArgumentsHolder argsHolderToUse = null;
 46         Object[] argsToUse = null;
 47 
 48         // 如果指定了构造参数则直接使用
 49         // 在调用getBean方法的时候指定方法参数
 50         if (explicitArgs != null) {
 51             argsToUse = explicitArgs;
 52         } else {
 53             // 没有指定,则尝试从配置文件中解析
 54             Object[] argsToResolve = null;
 55             // 同步
 56             synchronized (mbd.constructorArgumentLock) {
 57                 // 获取缓存中的构造函数或者工厂方法
 58                 factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
 59                 if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
 60                     // 获取缓存中的构造参数
 61                     // Found a cached factory method...
 62                     argsToUse = mbd.resolvedConstructorArguments;
 63                     if (argsToUse == null) {
 64                         argsToResolve = mbd.preparedConstructorArguments;
 65                     }
 66                 }
 67             }
 68             // 缓存中存在,则解析存储在BeanDefinition中的参数
 69             // 如给定方法的构造函数 f(int ,int),通过此方法后就会把配置文件中的("1","1")转换为(1,1)
 70             // 缓存中的值可能是原始值,也可能是最终值
 71             if (argsToResolve != null) {
 72                 argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
 73             }
 74         }
 75 
 76         if (factoryMethodToUse == null || argsToUse == null) {
 77             // Need to determine the factory method...
 78             // Try all methods with this name to see if they match the given arguments.
 79             // 获取工厂方法的类的全类名
 80             factoryClass = ClassUtils.getUserClass(factoryClass);
 81 
 82             List<Method> candidateList = null;
 83             // 同步
 84             if (mbd.isFactoryMethodUnique) {
 85                 // 获取工厂方法
 86                 if (factoryMethodToUse == null) {
 87                     factoryMethodToUse = mbd.getResolvedFactoryMethod();
 88                 }
 89                 // 获取所有待定的工厂方法
 90                 if (factoryMethodToUse != null) {
 91                     candidateList = Collections.singletonList(factoryMethodToUse);
 92                 }
 93             }
 94             // 如果工厂方法为空,则通过getCandidateMethods获取所有的待定方法
 95             if (candidateList == null) {
 96                 candidateList = new ArrayList<>();
 97                 Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
 98                 for (Method candidate : rawCandidates) {
 99                     if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
100                         candidateList.add(candidate);
101                     }
102                 }
103             }
104 
105             // 通过工厂方法创建bean
106             if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
107                 Method uniqueCandidate = candidateList.get(0);
108                 if (uniqueCandidate.getParameterCount() == 0) {
109                     mbd.factoryMethodToIntrospect = uniqueCandidate;
110                     synchronized (mbd.constructorArgumentLock) {
111                         mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
112                         mbd.constructorArgumentsResolved = true;
113                         mbd.resolvedConstructorArguments = EMPTY_ARGS;
114                     }
115                     bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
116                     return bw;
117                 }
118             }
119 
120             Method[] candidates = candidateList.toArray(new Method[0]);
121             // 排序构造函数
122             // public构造函数优先参数数量降序,非public构造函数参数数量降序
123             AutowireUtils.sortFactoryMethods(candidates);
124 
125             // 用于承载解析后的构造函数参数的值
126             ConstructorArgumentValues resolvedValues = null;
127             boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
128             int minTypeDiffWeight = Integer.MAX_VALUE;
129             Set<Method> ambiguousFactoryMethods = null;
130 
131             int minNrOfArgs;
132             if (explicitArgs != null) {
133                 minNrOfArgs = explicitArgs.length;
134             } else {
135                 // We don't have arguments passed in programmatically, so we need to resolve the
136                 // arguments specified in the constructor arguments held in the bean definition.
137                 // getBean没有传递参数,则需要解析保存在BeanDefinition构造函数中指定的参数
138                 if (mbd.hasConstructorArgumentValues()) {
139                     // 构造函数参数
140                     ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
141                     resolvedValues = new ConstructorArgumentValues();
142                     // 解析构造函数参数
143                     // 将bean的构造函数解析为resolvedValues对象,其中会涉及到其他的bean
144                     minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
145                 } else {
146                     minNrOfArgs = 0;
147                 }
148             }
149 
150             // 记录UnsatisfiedDependencyException异常集合
151             LinkedList<UnsatisfiedDependencyException> causes = null;
152 
153             // 遍历candidates
154             for (Method candidate : candidates) {
155                 // 方法体参数
156                 Class<?>[] paramTypes = candidate.getParameterTypes();
157 
158                 if (paramTypes.length >= minNrOfArgs) {
159                     // 保存参数对象
160                     ArgumentsHolder argsHolder;
161                     // getBean()传递了参数
162                     if (explicitArgs != null) {
163                         // Explicit arguments given -> arguments length must match exactly.
164                         // 显示给定参数,参数长度必须完全匹配
165                         if (paramTypes.length != explicitArgs.length) {
166                             continue;
167                         }
168                         // 根据参数创建参数持有者ArgumentsHolder对象
169                         argsHolder = new ArgumentsHolder(explicitArgs);
170                     } else {
171                         // Resolved constructor arguments: type conversion and/or autowiring necessary.
172                         // 根据提供的参数,解析构造函数
173                         try {
174                             String[] paramNames = null;
175                             // 获取ParameterNameDiscoverer对象
176                             // ParameterNameDiscoverer用于解析方法和构造函数的参数名,为参数名称探测器
177                             ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
178                             // 获取指定构造函数的参数名
179                             if (pnd != null) {
180                                 paramNames = pnd.getParameterNames(candidate);
181                             }
182                             // 在已解析构造函数参数值的情况下,创建一个参数持有者ArgumentsHolder对象
183                             argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
184                                                              paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
185                         } catch (UnsatisfiedDependencyException ex) {
186                             if (logger.isTraceEnabled()) {
187                                 logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
188                             }
189                             // Swallow and try next overloaded factory method.
190                             if (causes == null) {
191                                 causes = new LinkedList<>();
192                             }
193                             // 发生UnsatisfiedDependencyException异常,添加到causes中
194                             causes.add(ex);
195                             continue;
196                         }
197                     }
198 
199                     // isLenientConstructorResolution判断解析构造函数的时候是否以宽松模式还是严格模式
200                     // 宽松模式:使用具有"最接近的模式"进行匹配
201                     // 严格模式:解析构造函数时,必须所有的都需要匹配,否则抛出异常
202                     int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
203                             argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
204                     // Choose this factory method if it represents the closest match.
205                     // 代表最接近的类型匹配,选择作为构造函数
206                     if (typeDiffWeight < minTypeDiffWeight) {
207                         factoryMethodToUse = candidate;
208                         argsHolderToUse = argsHolder;
209                         argsToUse = argsHolder.arguments;
210                         minTypeDiffWeight = typeDiffWeight;
211                         ambiguousFactoryMethods = null;
212                     }
213                     // Find out about ambiguity: In case of the same type difference weight
214                     // for methods with the same number of parameters, collect such candidates
215                     // and eventually raise an ambiguity exception.
216                     // However, only perform that check in non-lenient constructor resolution mode,
217                     // and explicitly ignore overridden methods (with the same parameter signature).
218                     // 如果具有相同参数数量的方法具有相同的类型差异权重,则收集此类型选项
219                     // 但是仅在非宽松模式构造函数解析模式下执行该检查,并显示忽略重写方法(具有相同的参数签名)
220                     else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
221                             !mbd.isLenientConstructorResolution() &&
222                             paramTypes.length == factoryMethodToUse.getParameterCount() &&
223                             !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
224                         // 查找多个可匹配的方法
225                         if (ambiguousFactoryMethods == null) {
226                             ambiguousFactoryMethods = new LinkedHashSet<>();
227                             ambiguousFactoryMethods.add(factoryMethodToUse);
228                         }
229                         ambiguousFactoryMethods.add(candidate);
230                     }
231                 }
232             }
233 
234             // 没有可执行的工厂方法,则抛出异常
235             if (factoryMethodToUse == null || argsToUse == null) {
236                 if (causes != null) {
237                     UnsatisfiedDependencyException ex = causes.removeLast();
238                     for (Exception cause : causes) {
239                         this.beanFactory.onSuppressedException(cause);
240                     }
241                     throw ex;
242                 }
243                 List<String> argTypes = new ArrayList<>(minNrOfArgs);
244                 if (explicitArgs != null) {
245                     for (Object arg : explicitArgs) {
246                         argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
247                     }
248                 } else if (resolvedValues != null) {
249                     Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
250                     valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
251                     valueHolders.addAll(resolvedValues.getGenericArgumentValues());
252                     for (ValueHolder value : valueHolders) {
253                         String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
254                                 (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
255                         argTypes.add(argType);
256                     }
257                 }
258                 String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
259                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
260                                                 "No matching factory method found: " +
261                                                         (mbd.getFactoryBeanName() != null ?
262                                                                 "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
263                                                         "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
264                                                         "Check that a method with the specified name " +
265                                                         (minNrOfArgs > 0 ? "and arguments " : "") +
266                                                         "exists and that it is " +
267                                                         (isStatic ? "static" : "non-static") + ".");
268             } else if (void.class == factoryMethodToUse.getReturnType()) {
269                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
270                                                 "Invalid factory method '" + mbd.getFactoryMethodName() +
271                                                         "': needs to have a non-void return type!");
272             } else if (ambiguousFactoryMethods != null) {
273                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
274                                                 "Ambiguous factory method matches found in bean '" + beanName + "' " +
275                                                         "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
276                                                         ambiguousFactoryMethods);
277             }
278 
279             // 将解析的构造函数加入缓存
280             if (explicitArgs == null && argsHolderToUse != null) {
281                 mbd.factoryMethodToIntrospect = factoryMethodToUse;
282                 argsHolderToUse.storeCache(mbd, factoryMethodToUse);
283             }
284         }
285 
286         // 创建bean对象,并设置到BeanWrapperImpl中
287         bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
288         return bw;
289     }

分析:

由于该方法实在是太长了,因此对其进行分段分析。

#1 首先初始化了BeanwrapperImpl,需确认工厂对象,获取工厂名称,如果工厂名不为null,则走如下流程:

 1       String factoryBeanName = mbd.getFactoryBeanName();
 2         // 工厂名不为空
 3         if (factoryBeanName != null) {
 4             // 如果工厂名和beanName相等,则抛出BeanDefinitionStoreException异常
 5             if (factoryBeanName.equals(beanName)) {
 6                 throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
 7                                                        "factory-bean reference points back to the same bean definition");
 8             }
 9             // 获取工厂实例
10             factoryBean = this.beanFactory.getBean(factoryBeanName);
11             // 如果是单例模式,并且已经缓存中已经存在beanName则抛出异常
12             if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
13                 throw new ImplicitlyAppearedSingletonException();
14             }
15             factoryClass = factoryBean.getClass();
16             isStatic = false;
17         } 

分析:

  • 如果factoryBeanName与beanName一样,则抛出BeanDefinitionStoreException异常。
  • 然后通过AbstractBeanFactory#getBean方法获取工厂实例对象。
  • 如果BeanDefinition为单例模式,且singletonObjects缓存中已经存在该bean对象了,则抛出异常。因为单例模式下且缓存中存在是不需要再次创建bean对象的,单例模式的bean只会实例化一次。

如果工厂名为null,则走如下分支:

 1      else {
 2             // 工厂名为空,则其可能是一个静态工厂
 3             // 静态工厂创建bean,必须要提供工厂的全类名
 4             // It's a static factory method on the bean class.
 5             if (!mbd.hasBeanClass()) {
 6                 throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
 7                                                        "bean definition declares neither a bean class nor a factory-bean reference");
 8             }
 9             factoryBean = null;
10             factoryClass = mbd.getBeanClass();
11             isStatic = true;
12         }

分析:

  • 如果BeanDefinition中没有解析类,则抛出异常,异常信息也描述得非常清晰:"bean definition的描述中既没有bean class也没有工厂的引用。
  • 将factoryClass设置为BeanDefinition的beanClass,并将isStatic=true,表明可能存在一个静态工厂。

#2 工厂对象确认后,需确认构造参数。

#2.1 如果explicitArgs存在,则直接使用该参数。explicitArgs是调用getBean方法的入参,如果该参数不为null,则可以确定构造函数的参数就是它了。

1     // 确定构造参数
2         // 如果getBean()已传递,则直接使用
3         if (explicitArgs != null) {
4             argsToUse = explicitArgs;
5         }

#2.2 如果未传入构造参数,则走如下分支:

 1 else {
 2             // 没有指定,则尝试从缓存中获取
 3             Object[] argsToResolve = null;
 4             // 同步
 5             synchronized (mbd.constructorArgumentLock) {
 6                 // 获取缓存中的构造函数或者工厂方法
 7                 factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
 8                 if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
 9                     // 获取缓存中的构造参数
10                     // Found a cached factory method...
11                     argsToUse = mbd.resolvedConstructorArguments;
12                     if (argsToUse == null) {
13                         argsToResolve = mbd.preparedConstructorArguments;
14                     }
15                 }
16             }
17             // 缓存中存在,则解析存储在BeanDefinition中的参数
18             // 如给定方法的构造函数 f(int ,int),通过此方法后就会把配置文件中的("1","1")转换为(1,1)
19             // 缓存中的值可能是原始值,也可能是最终值
20             if (argsToResolve != null) {
21                 argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
22             }
23         }

分析:

整个流程其实就是尝试从缓存中获取构造函数参数,如果存在则通过resolvePreparedArguments进行转换,由于缓存中的值可能是最终值,也可能不是最终值。比如构造函数中的类型为Integer类型的1,但缓存中的类型有可能是String类型的"1",所以即便是从缓存中得到了构造参数,也需要经过一番的类型转换才能确保参数类型完全对应。关于resolvePreparedArguments函数的解析,将在后续文章中体现。

#2.3 如果缓存中未获取到构造参数,则走如下分支:

 1 if (factoryMethodToUse == null || argsToUse == null) {
 2             // Need to determine the factory method...
 3             // Try all methods with this name to see if they match the given arguments.
 4             // 获取工厂方法的类的全类名
 5             factoryClass = ClassUtils.getUserClass(factoryClass);
 6 
 7             List<Method> candidateList = null;
 8             // 同步
 9             if (mbd.isFactoryMethodUnique) {
10                 // 获取工厂方法
11                 if (factoryMethodToUse == null) {
12                     factoryMethodToUse = mbd.getResolvedFactoryMethod();
13                 }
14                 // 获取所有待定的工厂方法
15                 if (factoryMethodToUse != null) {
16                     candidateList = Collections.singletonList(factoryMethodToUse);
17                 }
18             }
19             // 如果工厂方法为空,则通过getCandidateMethods获取所有的待定方法
20             if (candidateList == null) {
21                 candidateList = new ArrayList<>();
22                 Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
23                 for (Method candidate : rawCandidates) {
24                     if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
25                         candidateList.add(candidate);
26                     }
27                 }
28             }
29 
30             // 通过工厂方法创建bean
31             if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
32                 Method uniqueCandidate = candidateList.get(0);
33                 if (uniqueCandidate.getParameterCount() == 0) {
34                     mbd.factoryMethodToIntrospect = uniqueCandidate;
35                     synchronized (mbd.constructorArgumentLock) {
36                         mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
37                         mbd.constructorArgumentsResolved = true;
38                         mbd.resolvedConstructorArguments = EMPTY_ARGS;
39                     }
40                     bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
41                     return bw;
42                 }
43             }

分析:

如果在缓存中未到构造参数,则尝试通过native方法获取工厂方法类的全类名,如果得到工厂方法只有一个时,则通过instantiate方法实例化bean,然后注入到BeanWrapperImpl中,直接返回。

instantiate方法会在后面进行分析。

#2.4 当上述分支都不满足,则走如下分支:通过提取配置文件中的信息来执行构建操作(代码还是有些长,分段来看):

 1           Method[] candidates = candidateList.toArray(new Method[0]);
 2             // 排序构造函数
 3             // public构造函数优先参数数量降序,非public构造函数参数数量降序
 4             AutowireUtils.sortFactoryMethods(candidates);
 5 
 6             // 用于承载解析后的构造函数参数的值
 7             ConstructorArgumentValues resolvedValues = null;
 8             boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
 9             int minTypeDiffWeight = Integer.MAX_VALUE;
10             Set<Method> ambiguousFactoryMethods = null;
11 
12             int minNrOfArgs;
13             if (explicitArgs != null) {
14                 minNrOfArgs = explicitArgs.length;
15             } else {
16                 // We don't have arguments passed in programmatically, so we need to resolve the
17                 // arguments specified in the constructor arguments held in the bean definition.
18                 // getBean没有传递参数,则需要解析保存在BeanDefinition构造函数中指定的参数
19                 if (mbd.hasConstructorArgumentValues()) {
20                     // 构造函数参数
21                     ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
22                     resolvedValues = new ConstructorArgumentValues();
23                     // 解析构造函数参数
24                     // 将bean的构造函数解析为resolvedValues对象,其中会涉及到其他的bean
25                     minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
26                 } else {
27                     minNrOfArgs = 0;
28                 }
29             }

分析:

  • 首先对工厂方法进行排序处理,排序规则:public工厂方法优先,参数数量降序,然后非public工厂方法优先,参数数量降序。
  • 如果入参中带有构造参数,则直接获取构造参数的个数。
  • 否则需从BeanDefinition中获取构造函数,并进行解析。xml配置文件的构造函数解析在加载BeanDefinition的过程中有提及。
  • 然后通过resolveConstructorArguments解析构造函数,并返回构造参数的最小个数。resolveConstructorArguments函数目前这里不做分析。

#2.4.1 上步中确定了构造参数,接下来进行构造函数的确定:

 1           // 遍历candidates
 2             for (Method candidate : candidates) {
 3                 // 方法体参数
 4                 Class<?>[] paramTypes = candidate.getParameterTypes();
 5 
 6                 if (paramTypes.length >= minNrOfArgs) {
 7                     // 保存参数对象
 8                     ArgumentsHolder argsHolder;
 9                     // getBean()传递了参数
10                     if (explicitArgs != null) {
11                         // Explicit arguments given -> arguments length must match exactly.
12                         // 显示给定参数,参数长度必须完全匹配
13                         if (paramTypes.length != explicitArgs.length) {
14                             continue;
15                         }
16                         // 根据参数创建参数持有者ArgumentsHolder对象
17                         argsHolder = new ArgumentsHolder(explicitArgs);
18                     } else {
19                         // Resolved constructor arguments: type conversion and/or autowiring necessary.
20                         // 根据提供的参数,解析构造函数
21                         try {
22                             String[] paramNames = null;
23                             // 获取ParameterNameDiscoverer对象
24                             // ParameterNameDiscoverer用于解析方法和构造函数的参数名,为参数名称探测器
25                             ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
26                             // 获取指定构造函数的参数名
27                             if (pnd != null) {
28                                 paramNames = pnd.getParameterNames(candidate);
29                             }
30                             // 在已解析构造函数参数值的情况下,创建一个参数持有者ArgumentsHolder对象
31                             argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
32                                                              paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
33                         } catch (UnsatisfiedDependencyException ex) {
34                             if (logger.isTraceEnabled()) {
35                                 logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
36                             }
37                             // Swallow and try next overloaded factory method.
38                             if (causes == null) {
39                                 causes = new LinkedList<>();
40                             }
41                             // 发生UnsatisfiedDependencyException异常,添加到causes中
42                             causes.add(ex);
43                             continue;
44                         }
45                     }
46 
47                     // isLenientConstructorResolution判断解析构造函数的时候是否以宽松模式还是严格模式
48                     // 宽松模式:使用具有"最接近的模式"进行匹配
49                     // 严格模式:解析构造函数时,必须所有的都需要匹配,否则抛出异常
50                     int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
51                             argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
52                     // Choose this factory method if it represents the closest match.
53                     // 代表最接近的类型匹配,选择作为构造函数
54                     if (typeDiffWeight < minTypeDiffWeight) {
55                         factoryMethodToUse = candidate;
56                         argsHolderToUse = argsHolder;
57                         argsToUse = argsHolder.arguments;
58                         minTypeDiffWeight = typeDiffWeight;
59                         ambiguousFactoryMethods = null;
60                     }
61                     // Find out about ambiguity: In case of the same type difference weight
62                     // for methods with the same number of parameters, collect such candidates
63                     // and eventually raise an ambiguity exception.
64                     // However, only perform that check in non-lenient constructor resolution mode,
65                     // and explicitly ignore overridden methods (with the same parameter signature).
66                     // 如果具有相同参数数量的方法具有相同的类型差异权重,则收集此类型选项
67                     // 但是仅在非宽松模式构造函数解析模式下执行该检查,并显示忽略重写方法(具有相同的参数签名)
68                     else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
69                             !mbd.isLenientConstructorResolution() &&
70                             paramTypes.length == factoryMethodToUse.getParameterCount() &&
71                             !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
72                         // 查找多个可匹配的方法
73                         if (ambiguousFactoryMethods == null) {
74                             ambiguousFactoryMethods = new LinkedHashSet<>();
75                             ambiguousFactoryMethods.add(factoryMethodToUse);
76                         }
77                         ambiguousFactoryMethods.add(candidate);
78                     }
79                 }
80             }

分析: 

  • 遍历所有构造函数。
  • 如果方法体参数大于等于最小参数个数,则判断是否传入了构造参数,如果是,则根据入参创建参数持有者对象ArgumentsHolder;否则通过方法体获取指定构造函数的参数,并创建参数持有者对象ArgumentsHolder。
  • 接着确定构造函数的解析是使用宽松模式还是严格模式。
  • 严格模式:解析构造函数时,必须所有参数都需要匹配,否则抛出异常。
  • 宽松模式:使用具有”最接近的模式”进行匹配。

#3.在参数与工厂构造函数确认好后,就可以进行bean的实例化了

 1 // 没有可执行的工厂方法,则抛出异常
 2             if (factoryMethodToUse == null || argsToUse == null) {
 3                 if (causes != null) {
 4                     UnsatisfiedDependencyException ex = causes.removeLast();
 5                     for (Exception cause : causes) {
 6                         this.beanFactory.onSuppressedException(cause);
 7                     }
 8                     throw ex;
 9                 }
10                 List<String> argTypes = new ArrayList<>(minNrOfArgs);
11                 if (explicitArgs != null) {
12                     for (Object arg : explicitArgs) {
13                         argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
14                     }
15                 } else if (resolvedValues != null) {
16                     Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
17                     valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
18                     valueHolders.addAll(resolvedValues.getGenericArgumentValues());
19                     for (ValueHolder value : valueHolders) {
20                         String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
21                                 (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
22                         argTypes.add(argType);
23                     }
24                 }
25                 String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
26                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
27                                                 "No matching factory method found: " +
28                                                         (mbd.getFactoryBeanName() != null ?
29                                                                 "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
30                                                         "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
31                                                         "Check that a method with the specified name " +
32                                                         (minNrOfArgs > 0 ? "and arguments " : "") +
33                                                         "exists and that it is " +
34                                                         (isStatic ? "static" : "non-static") + ".");
35             } else if (void.class == factoryMethodToUse.getReturnType()) {
36                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
37                                                 "Invalid factory method '" + mbd.getFactoryMethodName() +
38                                                         "': needs to have a non-void return type!");
39             } else if (ambiguousFactoryMethods != null) {
40                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
41                                                 "Ambiguous factory method matches found in bean '" + beanName + "' " +
42                                                         "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
43                                                         ambiguousFactoryMethods);
44             }
45 
46             // 将解析的构造函数加入缓存
47             if (explicitArgs == null && argsHolderToUse != null) {
48                 mbd.factoryMethodToIntrospect = factoryMethodToUse;
49                 argsHolderToUse.storeCache(mbd, factoryMethodToUse);
50             }
51         }
52 
53         // 创建bean对象,并设置到BeanWrapperImpl中
54         bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
55         return bw;

分析:

  • 如果工厂方法为空或构造参数为空,经过一系列异常判断后,最后会将解析的构造函数加入缓存。
  • 然后通过instantiate方法创建bean对象,并注入到BeanWrapperImpl中,最后返回bw。
 1 // ConstructorResolver
 2 
 3     public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {
 4             synchronized (mbd.constructorArgumentLock) {
 5                 mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
 6                 mbd.constructorArgumentsResolved = true;
 7                 if (this.resolveNecessary) {
 8                     mbd.preparedConstructorArguments = this.preparedArguments;
 9                 } else {
10                     mbd.resolvedConstructorArguments = this.arguments;
11                 }
12             }
13         }
14 
15 // RootBeanDefinition.java
16       /**
17      * 构造函数的缓存锁
18      * Common lock for the four constructor fields below.
19      */
20     final Object constructorArgumentLock = new Object();
21 
22     /**
23      * 缓存已经解析的构造函数或工厂方法<br/>
24      * Package-visible field for caching the resolved constructor or factory method.
25      */
26     @Nullable
27     Executable resolvedConstructorOrFactoryMethod;
28 
29     /**
30      * 标记字段:标记构造函数、参数是否已经解析,默认为false<br/>
31      * Package-visible field that marks the constructor arguments as resolved.
32      */
33     boolean constructorArgumentsResolved = false;
34 
35     /**
36      * 缓存已经解析的构造函数参数,包括可见字段<br/>
37      * Package-visible field for caching fully resolved constructor arguments.
38      */
39     @Nullable
40     Object[] resolvedConstructorArguments;

分析:

这里就是将构造函数、构造参数进行缓存,也就是最开始为什么要从缓存中获取的原因。

ConstructorResolver#instantiate

 1 private Object instantiate(String beanName, RootBeanDefinition mbd,
 2                                @Nullable Object factoryBean, Method factoryMethod, Object[] args) {
 3 
 4         try {
 5 
 6             if (System.getSecurityManager() != null) {
 7                 return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
 8                                                              this.beanFactory.getInstantiationStrategy().instantiate(
 9                                                                      mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args),
10                                                      this.beanFactory.getAccessControlContext());
11             } else {
12                 return this.beanFactory.getInstantiationStrategy().instantiate(
13                         mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
14             }
15         } catch (Throwable ex) {
16             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
17                                             "Bean instantiation via factory method failed", ex);
18         }
19     }

分析:

该方法就是创建bean对象的方法,这里会委托调用SimpleInstantiationStrategy#instantiate方法。

 1 public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
 2                               @Nullable Object factoryBean, final Method factoryMethod, Object... args) {
 3 
 4         try {
 5             // 设置method可访问
 6             if (System.getSecurityManager() != null) {
 7                 AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
 8                     ReflectionUtils.makeAccessible(factoryMethod);
 9                     return null;
10                 });
11             } else {
12                 ReflectionUtils.makeAccessible(factoryMethod);
13             }
14 
15             // 获得原method对象
16             Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
17             try {
18                 // 设置新的method对象到currentlyInvokedFactoryMethod中
19                 currentlyInvokedFactoryMethod.set(factoryMethod);
20                 // 创建bean对象 通过反射执行工厂方法并返回创建的bean对象
21                 Object result = factoryMethod.invoke(factoryBean, args);
22                 // 未创建,则创建NullBean对象
23                 if (result == null) {
24                     result = new NullBean();
25                 }
26                 return result;
27             } finally {
28                 // 设置老的method对象到currentlyInvokedFactoryMethod中
29                 if (priorInvokedFactoryMethod != null) {
30                     currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
31                 } else {
32                     currentlyInvokedFactoryMethod.remove();
33                 }
34             }
35         } catch (IllegalArgumentException ex) {
36             throw new BeanInstantiationException(factoryMethod,
37                                                  "Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
38                                                          "args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
39         } catch (IllegalAccessException ex) {
40             throw new BeanInstantiationException(factoryMethod,
41                                                  "Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
42         } catch (InvocationTargetException ex) {
43             String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
44             if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
45                     ((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
46                 msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
47                         "declaring the factory method as static for independence from its containing instance. " + msg;
48             }
49             throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
50         }
51     }

分析:

  • 首先设置方法的可访问性。
  • 然后更新currentlyInvokedFactoryMethod缓存的方法。
  • 核心点是通过反射执行工厂方法创建bean对象。
  • 最后再次更新currentlyInvokedFactoryMethod。

至此通过工厂方法实例化Bean对象的过程分析完毕,真的是不容易,当然文中还有些方法未详细分析,后续再进行查漏补缺。

总结

instantiateUsingFactoryMethod方法体很大,但是其核心点就是确定工厂对象,获取构造函数和构造参数,最后通过SimpleInstantiationStrategy#instantiate反射执行工厂方法创建bean对象。


by Shawn Chen,2019.04.24日,下午。

原文地址:https://www.cnblogs.com/developer_chan/p/10758926.html