DefaultListableBeanFactory 对象使用 ConstructorResolver 对象进行对象的创建,该对象提供 autowireConstructor 、instantiateUsingFactoryMethod 与 resolveFactoryMethodIfPossible 三个方法分别用于使用构造方法创建对象、使用对象工厂方法以及尝试解析对象注册表的对象工厂方法。
1 属性及构造方法
1.1 常量
ConstructorResolver 类拥有三个不同的常量值,分别为空参数数组 EMPTY_ARGS、用于缓存自动注入参数表时及缓存线程注入点的 currentInjectionPoint ;
class ConstructorResolver {
private static final Object[] EMPTY_ARGS = new Object[0];
private static final Object autowiredArgumentMarker = new Object();
private static final NamedThreadLocal<InjectionPoint> currentInjectionPoint =
new NamedThreadLocal<>("Current injection point");
}
1.2 属性变量
ConstructorResolver 对象只有一个保存当前对象工厂的 beanFactory 属性;
class ConstructorResolver {
private final AbstractAutowireCapableBeanFactory beanFactory;
}
1.3 构造方法
ConstructorResolver 的构造方法直接使用入参值对 beanFactory 属性值进行初始化;
class ConstructorResolver {
public ConstructorResolver(AbstractAutowireCapableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
this.logger = beanFactory.getLogger();
}
}
2 类方法
2.1 autowireConstructor 方法
autowireConstructor 方法首先新建一个空的 BeanWrapperImpl 封装对象并调用对象工厂属性的 initBeanWrapper 方法对其进行初始化;随后为保存构造方法所使用的参数的 argsToUse 局部变量进行赋值,在 explicitArgs 属性不为空时直接将其初始化为该参数值,否则 mbd 参数的构造方法或对象工厂方法已完成了解析,即 mdb 参数的 resolvedConstructorOrFactoryMethod 属性值不为空时将该属性值保存到 constructorToUse 变量中,在其值不为空且 mbd 的构造方法属性已被解析,即 constructorArgumentsResolved 属性已置为 true,会将缓存的构造方法参数值保存到 argsToUse 变量中,若其不为空且注册表对象的 preparedConstructorArguments 属性值不为空时,进一步调用 resolvePreparedArguments 方法对方法参数进一步解析并保存到 argsToUse 变量之中;
若经过上述过程,constructorToUse 与 argsToUse 局部变量值都不为空时,直接调用 instantiate 方法初始化对象并保存到已完成初始化的 BeanWrapperImpl 封装对象之中并返回该对象;否则首先在 chosenCtors 参数为空时则将其更新为类所拥有的构造方法对象数组,之后在 candidates 参数只有一个无参方法对象元素、explicitArgs 为 null 且注册表对象没有构造方法参数,即使用的是对象的无参构造方法时,分别将 mbd 参数的 resolvedConstructorOrFactoryMethod、constructorArgumentsResolved 及 resolvedConstructorArguments 三个属性分别更新为该无参方法对象、true 及 EMPTY_ARGS 空参数数组,同时使用 instantiate 方法对其进行初始化并保存到 BeanWrapperImpl 封装对象之中然后直接返回该对象;
之后对在 explicitArgs 参数不为 null 时,将 minNrOfArgs 局部变量值更新为该参数的大小,否则使用 resolveConstructorArguments 方法解析 mbd 参数的 constructorArgumentValues 属性值并将其解析结果保存到 resolvedValues 局部变量中并将其标识的构造方法参数数量更新保存到 minNrOfArgs 变量中;之后对排序的 candidates 构造函数候选对象数组进行遍历,跳过其中方法参数数小于构造方法参数数量的元素,首先在 constructorToUse、constructorToUse 变量都不为空且 argsToUse 变量中的参数大小值大于当前方法参数数时,直接中断遍历,否则随后在 resolvedValues 参数不为 null 时,调用 createArgumentArray 方法将其对应的所有参数解析出来并保存到 argsHolder 变量中,在 resolvedValues 参数为 null 时,则是将 argsHolder 变量值更新为使用 explicitArgs 参数创建的 ArgumentsHolder 对象;之后根据 mbd 参数的构造函数参数值差距模式获取当前方法参数数差异模式,并在其值小于 minTypeDiffWeight 局部变量值时,分别将 constructorToUse、argsHolderToUse、argsToUse、minTypeDiffWeight 及 ambiguousConstructors 变量分别更新为 candidate、argsHolder 、argsHolder 的 arguments 属性、typeDiffWeight 变量值及 null 值,在 constructorToUse 变量不为 null 且 typeDiffWeight 与 minTypeDiffWeight 想等时空时,将候选对象保存到 ambiguousConstructors 变量之中;
在 explicitArgs 变量不为 null 且 argsHolderToUse 变量不为 null 时,调用 argsHolderToUse 变量的 storeCache 方法将 constructorToUse 变量值缓存到 mbd 参数中;最后对创建对象进行初始化并保存到 bw 变量中并返回
class ConstructorResolver {
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Constructor<?> uniqueCandidate = candidates[0];
if (uniqueCandidate.getParameterCount() == 0) {
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// Need to resolve the constructor.
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
LinkedList<UnsatisfiedDependencyException> causes = null;
for (Constructor<?> candidate : candidates) {
int parameterCount = candidate.getParameterCount();
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
Class<?>[] paramTypes = candidate.getParameterTypes();
if (resolvedValues != null) {
try {
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
else {
// Explicit arguments given -> arguments length must match exactly.
if (parameterCount != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
if (constructorToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
}
instantiate 方法直接执行 beanFactory 对象工厂属性中的 instantiationStrategy 初始化策略属性的 instantiate 方法进行初始化并返回;
class ConstructorResolver {
private Object instantiate(
String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {
try {
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
this.beanFactory.getAccessControlContext());
}
else {
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via constructor failed", ex);
}
}
}
getUserDeclaredConstructor 方法用于获取 constructor 对应实际用户类的构造方法数组;
class ConstructorResolver {
protected Constructor<?> getUserDeclaredConstructor(Constructor<?> constructor) {
Class<?> declaringClass = constructor.getDeclaringClass();
Class<?> userClass = ClassUtils.getUserClass(declaringClass);
if (userClass != declaringClass) {
try {
return userClass.getDeclaredConstructor(constructor.getParameterTypes());
}
catch (NoSuchMethodException ex) {
// No equivalent constructor on user class (superclass)...
// Let's proceed with the given constructor as we usually would.
}
}
return constructor;
}
}
2.2 resolveFactoryMethodIfPossible 方法
resolveFactoryMethodIfPossible 方法尝试解析 mbd 注册表中解析出对应的对象工厂方法;其首先在 mbd 拥有对应的对象工厂对象名时同时将 isStatic 变量与 factoryClass 置为 false 与 beanFactory 对应的对象工厂类型,否则将 isStatic 与 factoryClass 变量分别初始化为 true 及 mbd 参数对应的对象类型;随后通过 getCandidateMethods 方法获取 factoryClass 类型中的候选方法对象列表并寻找其中满足条件的非重方法对象,并将其保存到 mbd 参数的 factoryMethodToIntrospect 属性中;
class ConstructorResolver {
public void resolveFactoryMethodIfPossible(RootBeanDefinition mbd) {
Class<?> factoryClass;
boolean isStatic;
if (mbd.getFactoryBeanName() != null) {
factoryClass = this.beanFactory.getType(mbd.getFactoryBeanName());
isStatic = false;
}
else {
factoryClass = mbd.getBeanClass();
isStatic = true;
}
Assert.state(factoryClass != null, "Unresolvable factory class");
factoryClass = ClassUtils.getUserClass(factoryClass);
Method[] candidates = getCandidateMethods(factoryClass, mbd);
Method uniqueCandidate = null;
for (Method candidate : candidates) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
if (uniqueCandidate == null) {
uniqueCandidate = candidate;
}
else if (isParamMismatch(uniqueCandidate, candidate)) {
uniqueCandidate = null;
break;
}
}
}
mbd.factoryMethodToIntrospect = uniqueCandidate;
}
}
isParamMismatch 方法判断 uniqueCandidate 与 candidate 方法对象参数的参数是否完全匹配;
class ConstructorResolver {
private boolean isParamMismatch(Method uniqueCandidate, Method candidate) {
int uniqueCandidateParameterCount = uniqueCandidate.getParameterCount();
int candidateParameterCount = candidate.getParameterCount();
return (uniqueCandidateParameterCount != candidateParameterCount ||
!Arrays.equals(uniqueCandidate.getParameterTypes(), candidate.getParameterTypes()));
}
}
getCandidateMethods 方法直接获取 factoryClass 参数中所有方法对象数组并返回;
class ConstructorResolver {
private Method[] getCandidateMethods(Class<?> factoryClass, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Method[]>) () ->
(mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods()));
}
else {
return (mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
}
}
}
2.3 instantiateUsingFactoryMethod 方法
instantiateUsingFactoryMethod 方法首先在 mbd 参数拥有管理工厂对象名时,我们在将工厂对象名与 beanName 参数作为依赖注册到 beanFactory 对象工厂中,并将 factoryClass 变量更新为 beanFactory 对象工厂中对应工厂对象的对象名,否则分别将 factoryClass 与 isStatic 变量分别更新为 mbd 对应类型值与 true;之后根据 autowireConstructor 参数是否为空,为 argsToUse、argsHolderToUse 及 factoryMethodToUse 局部变量进行赋值,其初始化逻辑和 autowireConstructor 方法一致;随后在 factoryMethodToUse 或 argsToUse 参数其中一个为空时,首先在 mbd 的 isFactoryMethodUnique 属性为 true 时,在 factoryMethodToUse 变量为空时,将其更新为 mbd 参数的 factoryMethodToIntrospect 属性值,随后在 factoryMethodToUse 属性不为空时,使用该变量创建 List 数组并更新到 candidates 参数中;之后若 candidates 参数中只有一个无参方法对象,直接使用该方法对象创建对象并更新 mbd 的对应属性值,并返回该值;随后对候选方法对象数组中参数数量大于最小需要的参数的方法对象,在处理过程中,也是根据 explicitArgs 参数值是否为空来初始化 argsHolder 局部变量值,其中在其不为空且 explicitArgs 参数大小与候选项参数大小不一致时直接返回,在其相等时,直接使用该参数创建 ArgumentsHolder 对象来初始化 argsHolder 变量值,在 explicitArgs 参数为 null 时也是通过 createArgumentArray 方法创建方法参数数组对象并初始化 argsHolder 变量值;随后也会根据 mbd 参数的构造函数参数值差距模式获取当前方法参数差异模式,并在其值小于 minTypeDiffWeight 局部变量值时,分别将 constructorToUse、argsHolderToUse、argsToUse、minTypeDiffWeight 及 ambiguousConstructors 变量分别更新为 candidate、argsHolder 、argsHolder 的 arguments 属性、typeDiffWeight 变量值及 null 值,在 constructorToUse 变量不为 null 且 typeDiffWeight 与 minTypeDiffWeight 想等时空时,将候选对象保存到 ambiguousConstructors 变量之中;
最后若 factoryMethodToUse 或 argsToUse 参数存在其中一个为空、factoryMethodToUse 变量的没有返回对象或 ambiguousFactoryMethods 变量不为 null 时直接抛出异常,之后在 explicitArgs 且 argsHolderToUse 都不为空时,将 factoryMethodToUse 属性缓存到 argsHolderToUse 属性中,最后使用 instantiate 方法创建对象并保存到 bw 封装对象中并返回;
class ConstructorResolver {
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;
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");
}
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
this.beanFactory.registerDependentBean(factoryBeanName, beanName);
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;
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
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);
}
}
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);
List<Method> candidates = null;
if (mbd.isFactoryMethodUnique) {
if (factoryMethodToUse == null) {
factoryMethodToUse = mbd.getResolvedFactoryMethod();
}
if (factoryMethodToUse != null) {
candidates = Collections.singletonList(factoryMethodToUse);
}
}
if (candidates == null) {
candidates = new ArrayList<>();
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
for (Method candidate : rawCandidates) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidates.add(candidate);
}
}
}
if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidates.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;
}
}
if (candidates.size() > 1) { // explicitly skip immutable singletonList
candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
}
ConstructorArgumentValues resolvedValues = null;
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Method> ambiguousFactoryMethods = null;
int minNrOfArgs;
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) {
int parameterCount = candidate.getParameterCount();
if (parameterCount >= minNrOfArgs) {
ArgumentsHolder argsHolder;
Class<?>[] paramTypes = candidate.getParameterTypes();
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);
}
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
paramTypes, paramNames, candidate, autowiring, candidates.size() == 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;
}
}
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this factory method if it represents the closest match.
if (typeDiffWeight < minTypeDiffWeight) {
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).
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 || argsToUse == 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 on class [" + factoryClass.getName() + "]: " +
(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") + ".");
}
else if (void.class == factoryMethodToUse.getReturnType()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid factory method '" + mbd.getFactoryMethodName() + "' on class [" +
factoryClass.getName() + "]: needs to have a non-void return type!");
}
else if (ambiguousFactoryMethods != null) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous factory method matches found on class [" + factoryClass.getName() + "] " +
"(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);
}
}
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
}
}
2.4 instantiate 方法
instantiate 方法直接调用 beanFactory 对象工厂属性中的 instantiationStrategy 初始化逻辑属性的 instantiate 方法进行对象初始化并返回;
class ConstructorResolver {
private Object instantiate(String beanName, RootBeanDefinition mbd,
@Nullable Object factoryBean, Method factoryMethod, Object[] args) {
try {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args),
this.beanFactory.getAccessControlContext());
}
else {
return this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via factory method failed", ex);
}
}
}
2.5 resolveConstructorArguments 方法
resolveConstructorArguments 方法在通过 beanFactory 属性、beanName 参数、 mbd 参数及 converter 参数创建的 BeanDefinitionValueResolver 对象的 resolveValueIfNecessary 方法完成对将 cargs 参数的 indexedArgumentValues 与 genericArgumentValues 属性值的解析后将其保存到 ConstructorArgumentValues 参数中然后返回所拥有的最小参数数量;
class ConstructorResolver {
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
int minNrOfArgs = cargs.getArgumentCount();
for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
int index = entry.getKey();
if (index < 0) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid constructor argument index: " + index);
}
if (index + 1 > minNrOfArgs) {
minNrOfArgs = index + 1;
}
ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
if (valueHolder.isConverted()) {
resolvedValues.addIndexedArgumentValue(index, valueHolder);
}
else {
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
ConstructorArgumentValues.ValueHolder resolvedValueHolder =
new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
}
}
for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
if (valueHolder.isConverted()) {
resolvedValues.addGenericArgumentValue(valueHolder);
}
else {
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(
resolvedValue, valueHolder.getType(), valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
resolvedValues.addGenericArgumentValue(resolvedValueHolder);
}
}
return minNrOfArgs;
}
}
2.5 createArgumentArray 方法
createArgumentArray 方法尝试将 resolvedValues 参数解析转化为 ArgumentsHolder 对象并返回,其首先通过 paramTypes 参数进行遍历,逐一解析并获取参数值,并将其中需要自动注入的对象名保存到 autowiredBeanNames 参数中,并在参数解析完成后调用 registerDependentBean 方法将依赖注入到 beanFactory 对象工厂之中;
class ConstructorResolver {
private ArgumentsHolder createArgumentArray(
String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
Class<?> paramType = paramTypes[paramIndex];
String paramName = (paramNames != null ? paramNames[paramIndex] : "");
// Try to find matching constructor argument value, either indexed or generic.
ConstructorArgumentValues.ValueHolder valueHolder = null;
if (resolvedValues != null) {
valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
// If we couldn't find a direct match and are not supposed to autowire,
// let's try the next generic, untyped argument value as fallback:
// it could match after type conversion (for example, String -> int).
if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
}
if (valueHolder != null) {
// We found a potential match - let's give it a try.
// Do not consider the same value definition multiple times!
usedValueHolders.add(valueHolder);
Object originalValue = valueHolder.getValue();
Object convertedValue;
if (valueHolder.isConverted()) {
convertedValue = valueHolder.getConvertedValue();
args.preparedArguments[paramIndex] = convertedValue;
}
else {
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
try {
convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" +
ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
Object sourceHolder = valueHolder.getSource();
if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
args.resolveNecessary = true;
args.preparedArguments[paramIndex] = sourceValue;
}
}
args.arguments[paramIndex] = convertedValue;
args.rawArguments[paramIndex] = originalValue;
}
else {
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
// No explicit match found: we're either supposed to autowire or
// have to fail creating an argument array for the given constructor.
if (!autowiring) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Ambiguous argument values for parameter of type [" + paramType.getName() +
"] - did you specify the correct bean references as arguments?");
}
try {
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = autowiredArgumentMarker;
args.resolveNecessary = true;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
}
}
}
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName +
"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
" to bean named '" + autowiredBeanName + "'");
}
}
return args;
}
}
2.6 resolvePreparedArguments 方法
resolvePreparedArguments 方法用于解析及获取 mbd 注册表对象中预准备参数;其对 argsToResolve 参数进行遍历,将其中的空 Object 对象元素值更新为 resolveAutowiredArgument 方法获取到的对应注入值,在其为 BeanMetadataElement 对象时,使用 valueResolver 变量的 resolveValueIfNecessary 方法解析该值并更新元素,在其为字符串时,调用 beanFactory 属性的 evaluateBeanDefinitionString 方法计算其实际值并更新元素,最后尝试使用创建的 customConverter 参数的 convertIfNecessary 方法将元素值转换为对应值;然后将处理后的值数组返回;
class ConstructorResolver {
private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
Executable executable, Object[] argsToResolve) {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
Class<?>[] paramTypes = executable.getParameterTypes();
Object[] resolvedArgs = new Object[argsToResolve.length];
for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
Object argValue = argsToResolve[argIndex];
MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex);
if (argValue == autowiredArgumentMarker) {
argValue = resolveAutowiredArgument(methodParam, beanName, null, converter, true);
}
else if (argValue instanceof BeanMetadataElement) {
argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
}
else if (argValue instanceof String) {
argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
}
Class<?> paramType = paramTypes[argIndex];
try {
resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(argValue) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
}
return resolvedArgs;
}
}
2.7 resolveAutowiredArgument 方法
resolveAutowiredArgument 方法在 param 参数类型为当前正在注入对象类型时,直接返回该值;否则使用 beanFactory 参数的 resolveDependency 方法解析依赖并返回其结果,若出现了 NoSuchBeanDefinitionException 异常且 fallback 参数为 true 时,在该参数为集合时,返回对应的空集合对象;
class ConstructorResolver {
@Nullable
protected Object resolveAutowiredArgument(MethodParameter param, String beanName,
@Nullable Set<String> autowiredBeanNames, TypeConverter typeConverter, boolean fallback) {
Class<?> paramType = param.getParameterType();
if (InjectionPoint.class.isAssignableFrom(paramType)) {
InjectionPoint injectionPoint = currentInjectionPoint.get();
if (injectionPoint == null) {
throw new IllegalStateException("No current InjectionPoint available for " + param);
}
return injectionPoint;
}
try {
return this.beanFactory.resolveDependency(
new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
}
catch (NoUniqueBeanDefinitionException ex) {
throw ex;
}
catch (NoSuchBeanDefinitionException ex) {
if (fallback) {
// Single constructor or factory method -> let's return an empty array/collection
// for e.g. a vararg or a non-null List/Set/Map parameter.
if (paramType.isArray()) {
return Array.newInstance(paramType.getComponentType(), 0);
}
else if (CollectionFactory.isApproximableCollectionType(paramType)) {
return CollectionFactory.createCollection(paramType, 0);
}
else if (CollectionFactory.isApproximableMapType(paramType)) {
return CollectionFactory.createMap(paramType, 0);
}
}
throw ex;
}
}
}
3 静态方法
3.1 setCurrentInjectionPoint 方法
setCurrentInjectionPoint 方法首先获取 currentInjectionPoint 静态变量中保存的当前进程对应的 InjectionPoint 对象,在 injectionPoint 属性不为空时将线程对应值更新为该参数值,否则移除当前线程对应注入点,最后返回之前保存的映射对象;
class ConstructorResolver {
static InjectionPoint setCurrentInjectionPoint(@Nullable InjectionPoint injectionPoint) {
InjectionPoint old = currentInjectionPoint.get();
if (injectionPoint != null) {
currentInjectionPoint.set(injectionPoint);
}
else {
currentInjectionPoint.remove();
}
return old;
}
}
4 内部类
4.1 ArgumentsHolder 类
ArgumentsHolder 类用于保存方法参数值;
4.1.1 属性及构造方法
4.1.1.1 类属性
ArgumentsHolder 类拥有三个保存对应参数数组的 rawArguments、arguments 与 preparedArguments 属性以及一个用于标识当前对象保存的值是否需要转换的 resolveNecessary 属性,其中 rawArguments 保存的是参数原始值数组、arguments 保存的则是转换后的参数值数组,而 preparedArguments 属性与 resolveNecessary 属性存在关联,只有在 resolveNecessary 属性为 true 时,该元素为源参数,否则为转换后参数;
class ConstructorResolver {
private static class ArgumentsHolder {
public final Object[] rawArguments;
public final Object[] arguments;
public final Object[] preparedArguments;
public boolean resolveNecessary = false;
}
}
4.1.1.2 构造方法
ArgumentsHolder 类拥有两个不同的构造方法,其中一个传入的是参数值大小,其将 rawArguments、arguments 与 preparedArguments 属性初始化为长度为 size 的空 Object 对象数组,而另一构造方法则只有一个 Object 对象数组参数,其直接将 rawArguments、arguments 与 preparedArguments 属性初始化入参值;
class ConstructorResolver {
private static class ArgumentsHolder {
public ArgumentsHolder(int size) {
this.rawArguments = new Object[size];
this.arguments = new Object[size];
this.preparedArguments = new Object[size];
}
public ArgumentsHolder(Object[] args) {
this.rawArguments = args;
this.arguments = args;
this.preparedArguments = args;
}
}
}
4.1.2 对象方法
4.1.2.1 getTypeDifferenceWeight 方法
getTypeDifferenceWeight 方法返回 paramTypes 参数与 arguments 或 rawArguments 属性差异中的小值;
class ConstructorResolver {
private static class ArgumentsHolder {
public int getTypeDifferenceWeight(Class<?>[] paramTypes) {
// If valid arguments found, determine type difference weight.
// Try type difference weight on both the converted arguments and
// the raw arguments. If the raw weight is better, use it.
// Decrease raw weight by 1024 to prefer it over equal converted weight.
int typeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.arguments);
int rawTypeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.rawArguments) - 1024;
return Math.min(rawTypeDiffWeight, typeDiffWeight);
}
}
}
4.1.2.2 getAssignabilityWeight 方法
getAssignabilityWeight 方法在 paramTypes 参数中存在与 arguments 对应元素不匹配直接返回最大整型数,在其存在与 rawArguments 对应元素不匹配直接返回最大整型数 - 512,否则返回最大整型数 - 1024;
class ConstructorResolver {
private static class ArgumentsHolder {
public int getAssignabilityWeight(Class<?>[] paramTypes) {
for (int i = 0; i < paramTypes.length; i++) {
if (!ClassUtils.isAssignableValue(paramTypes[i], this.arguments[i])) {
return Integer.MAX_VALUE;
}
}
for (int i = 0; i < paramTypes.length; i++) {
if (!ClassUtils.isAssignableValue(paramTypes[i], this.rawArguments[i])) {
return Integer.MAX_VALUE - 512;
}
}
return Integer.MAX_VALUE - 1024;
}
}
}
4.1.2.3 storeCache 方法
storeCache 方法首先分别将 mdb 参数的 resolvedConstructorOrFactoryMethod 与 constructorArgumentsResolved 属性更新为 constructorOrFactoryMethod 参数值与 true,随后若 resolveNecessary 属性为 true 将 mbd 参数的 preparedConstructorArguments 属性更新为 preparedArguments 参数值,否则则将该属性更新为 arguments 属性值;
class ConstructorResolver {
private static class ArgumentsHolder {
public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
mbd.constructorArgumentsResolved = true;
if (this.resolveNecessary) {
mbd.preparedConstructorArguments = this.preparedArguments;
}
else {
mbd.resolvedConstructorArguments = this.arguments;
}
}
}
}
}
4.2 ConstructorPropertiesChecker 类
ConstructorPropertiesChecker 类只有一个用于解析构造方法对象参数名数组的 evaluate 静态方法,其在 candidate 参数使用 ConstructorProperties 注解修饰时,直接返回其 value 属性值,否则直接返回 null;
class ConstructorResolver {
private static class ConstructorPropertiesChecker {
@Nullable
public static String[] evaluate(Constructor<?> candidate, int paramCount) {
ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);
if (cp != null) {
String[] names = cp.value();
if (names.length != paramCount) {
throw new IllegalStateException("Constructor annotated with @ConstructorProperties but not " +
"corresponding to actual number of parameters (" + paramCount + "): " + candidate);
}
return names;
}
else {
return null;
}
}
}
}