createBeanInstance 是Spring实例化的核心代码,它根据不同的情况会调用四种实例化方法。
- obtainFromSupplier 通过Supplier实例化
- instantiateUsingFactoryMethod 通过工厂方法
- autowireConstructor 用合适的构造函数
- instantiateBean 用无参构造函数
第一种很简单,看一下代码就能发现Supplier接口只有一个get方法,就通过这个实例化。
第二第三种比较复杂,也比较相近,本文详细分析。
第四种也很简单,当找不到其它构造函数时,就用无参的,就像兜底的一样。
instantiateUsingFactoryMethod
通过工厂方法进行实例化,简单地想一下,肯定需要下面三个东西:
- 工厂方法的bean,如果是静态工厂方法的话就不需要这个了。
- 要调用的工厂方法
- 需要传入的参数
有了上述概念后,来看代码,代码很长很复杂,但是总体上讲就是先解析上面这三个东西,然后进行实例化。
代码入口
// AbstractAutowireCapableBeanFactory
createBeanInstance{
//...
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
//...
}
// AbstractAutowireCapableBeanFactory
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
实际干活的代码
为了更好理解,省略了部分代码,但还是很长…
代码都有详细的注释,并且很明显地分成了三部分,应该能看懂。
// ConstructorResolver
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs){
// 建立一个BeanWrapper
BeanWrapperImpl bw = new BeanWrapperImpl();
//----------------------------------1. 首先确定factoryBean--------------------------------
// 如果是非静态的,获取factoryBean实例,否则null
Object factoryBean;
// 工厂类
Class<?> factoryClass;
// 非静态false,静态true
boolean isStatic;
// ...
//---------------------2. 确定factoryMethod 和 argsToUse(需要传的参数)---------------------
// 用到的factoryMethod
Method factoryMethodToUse = null;
ArgumentsHolder argsHolderToUse = null;
// 需要传入的参数
Object[] argsToUse = null;
//------------------------------2.1 显式传参 或者 从缓存中拿-------------------------------
// 如果显式传参就不用去解析参数了,但是要通过2.2解析factoryMethodToUse
if (explicitArgs != null) {
argsToUse = explicitArgs;
} else {
// 从缓存中拿
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
// 获取缓存的方法
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
// 获取缓存的可以直接使用的参数
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
// 获取缓存的待解析的参数
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
// 解析从未解析的参数: 字符串“3” -> 数字3
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
}
}
// 如果通过上述步骤argsToUse 和 factoryMethodToUse 都确定了就直接到第三步,否则到2.2
//-----------------------2.2 argsToUse 或者 factoryMethodToUse还没确定-------------------
if (factoryMethodToUse == null || argsToUse == null) {
// 获得所有符合条件的method
// 条件有两个 1. 如果是静态工厂方法只要static的,否则就只要非static的 2. 是工厂方法
if (candidates == null) {
//...
}
// 只有一个方法且不需要传参,并且配置文件中也没有定义入参。
if (candidates.size() == 1 && explicitArgs == null &&
!mbd.hasConstructorArgumentValues()) {
// ...
// 创建完beanwrapper直接返回
return bw;
}
// 如果有很多candidates,先按public,非public排序,再按参数量降序
if (candidates.size() > 1) {
candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
}
// 从配置文件中解析的参数
ConstructorArgumentValues resolvedValues = null;
// autowire == "constructor"
boolean autowiring = (mbd.getResolvedAutowireMode() ==
AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
// 类型差分数
int minTypeDiffWeight = Integer.MAX_VALUE;
// 类型差分数 并列最低的FactoryMethod们
Set<Method> ambiguousFactoryMethods = null;
// 配置文件中直接定义 或者 显式传参的数量
int minNrOfArgs;
// 解析配置文件中定义的参数
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs,
resolvedValues);
// 循环每个方法,找最合适的方法
for (Method candidate : candidates) {
// ...
// 获取解析器
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
// 获取当前方法需要的参数定义
paramNames = pnd.getParameterNames(candidate);
}
// 根据配置文件中定义好的入参,工厂方法要求的参数,autowiring模式等获得所有参数。
// 如果autowiring不是constructor,那配置文件中的入参就得和方法要求的参数完全一致,否则就
// 会报错
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
paramTypes, paramNames, candidate,
autowiring, candidates.size() == 1);
// 根据实际获得的参数argsHolder和需要的参数,得到类型差异分
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) :
argsHolder.getAssignabilityWeight(paramTypes));
// 找最小的typeDiffWeight对应的factoryMethodToUse和argsToUse
if (typeDiffWeight < minTypeDiffWeight) {
factoryMethodToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null;
}
if (/*有并列的typeDiffWeight*/){
ambiguousFactoryMethods.add(candidate);
}
}
// ...
// 存缓存
if (explicitArgs == null && argsHolderToUse != null) {
mbd.factoryMethodToIntrospect = factoryMethodToUse;
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
//--------------------------------------3. 实例化-----------------------------------------
// 根据得到的factoryBean(如果是静态工厂方法就是null),factoryMethodToUse,argsToUse
// 进行实例化
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean,
factoryMethodToUse, argsToUse));
return bw;
}
总结
主要就是三部分:
-
解析工厂类,工厂bean,工厂方法是不是static
-
找最合适的工厂方法factoryMethodToUse, 和 需要传入的参数argsToUse
2.1 根据static或者不是static找到所有的候选方法
2.2 遍历所有的候选方法,按当前候选方法需要的形参去获得实参(从配置文件中找 或者 可以autowire到的) ,根据形参和实际获得的实参,得到差异分typeDiffWeight,取最小差异分对应的候选方法作为factoryMethodToUse,对应的实参作为argsToUse。
-
用工厂bean,factoryMethodToUse,argsToUse进行实例化
理清楚了其实也不是很复杂hhhh
autowireConstructor
这个其实就是低配版的instantiateUsingFactoryMethod。主要少了下面这两部分
- 不需要工厂,所以不用解析工厂类,工厂bean
- 构造函数没有static的,所以不需要解析isStatic
其它部分基本是一样的。就直接看代码吧,这次放完整的代码了。
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
// --------------------------------1. 确定构造函数 和 入参----------------------------------
// 构造函数
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
// 传入的参数
Object[] argsToUse = null;
// -------------------------------1.1 从缓存中拿------------------------------------
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, true);
}
}
//-----------------------1.2 constructorToUse 或者 argsToUse还没解析出来----------------
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 " +
"(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 in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
// 存缓存
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
// ----------------------------------2 实例化---------------------------------------------
Assert.state(argsToUse != null, "Unresolved constructor arguments");
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
总结
从代码可以看出来它只有两部分了,不需要解析工厂相关的东西了,其它差不多。
instantiateBean
这个就是调用无参构造函数,就不需要各种解析过程了,直接用就完事了。