之前分析了 bean 创建的基本思路,现在我们看看第一步,如何获取一个初步的 bean 框架 BeanWrapper。
createBeanInstance 源码概述
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 解析 class
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
...
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 如果有工厂方法,则使用工厂方法初始化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 一个类有多个构造函数,需要根据参数锁定对应的构造函数
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 如果已经解析过了,则直接使用解析好的构造函数方法
if (resolved) {
if (autowireNecessary) {
// 构造函数自动注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默认构造函数
return instantiateBean(beanName, mbd);
}
}
// 解析构造函数
// Candidate constructors for autowiring?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
// 构造函数自动注入
return autowireConstructor(beanName, mbd, ctors, null);
}
// 使用默认构造函数
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
上述源码主要分为两个部分:
- 如果是在 RootBeanDefinition 中存在的 factoryMethodName 属性,或者说在配置文件中配置了 factory-method,那么 Spring 会尝试使用 instantiateUsingFactoryMethod(beanName, mbd, args) 方法,根据 RootBeanDefinition 的内容配置生成 bean 实例。
- 解析构造函数并进行构造函数实例化。因为一个 bean 对应的类中可能会有多个构造函数,而每个构造函数的参数不同,Spring 根据参数确定使用哪个构造函数,但是判断过程比较消耗性能,所以已经解析过的会从 RootBeanDefinition 的 resolvedConstructorOrFactoryMethod 中获取。
autowireConstructor
该函数对应了带有参数的构造器的 bean 实例化,首先看看源码。
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;
// explicitArgs 是从 getBean 方法中直接传入的
// 如果 explicitArgs 不为空,则直接使用
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
// explicitArgs 为空,则尝试从缓存和配置文件中获取对应参数
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;
}
}
}
// 若缓存中存在,解析参数类型,如给定构造函数 A(int, int) 则会把配置中的 ("1", "1")
// 转换为 (1, 1)
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
// 缓存中没有数据
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());
}
...
}
// 若只有一个构造函数,并且函数没有参数,则判定为已经解析完成,缓存数据,并实例化
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);
}
// 排序构造函数
// public 函数优先,参数数量降序,非 public 参数数量降序
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
LinkedList<UnsatisfiedDependencyException> causes = null;
for (Constructor<?> candidate : candidates) {
Class<?>[] paramTypes = candidate.getParameterTypes();
// 已经找到对应的构造函数或者数量上已经不能满足,直接结束寻找
if (constructorToUse != null && argsToUse != null && argsToUse.length > paramTypes.length) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
// 数量不匹配
if (paramTypes.length < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
if (resolvedValues != null) {
// 有参数则根据值构造对应参数类型的参数
try {
// 从注释获取参数名称
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
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);
}
...
}
else {
// Explicit arguments given -> arguments length must match exactly.
if (paramTypes.length != 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;
}
// 出现相似度一样的构造函数,存入 set
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);
}
}
// 构造结果放入 BeanWrapper 中
Assert.state(argsToUse != null, "Unresolved constructor arguments");
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
上述源码总结一下,可以分为一下几个方面:
-
构造函数参数的确定
- 根据 explicitArgs 参数判断
如果传入 explicitArgs 参数不为空,则直接用这个参数,作为构造函数参数;explicitArgs 参数来自于 getBean(String name, Object… args) 的 args 部分。 - 缓存中获取
- 配置文件中获取
通过 mbd.getConstructorArgumentValues() 获取配置文件中构造函数的内容。
- 根据 explicitArgs 参数判断
-
构造函数的确定
遍历所有的待选构造器,根据参数的个数和类型进行相似度判断。由于在配置文件中并不只使用参数位置索引的方式去创建,同样还支持指定参数名称进行参数值设置。所以这种情况下还需要获取构造函数的参数名称。Spring 提供了两种获取参数名称的方式:一是通过注解的方式直接获取;二是使用 Spring 中提供的工具类 ParameterNameDiscoverer 来获取。
-
根据确定的构造函数转换对应的参数类型
根据要求的类型,通过 Spring 中的或者自定义的参数转换器进行自动转换。 -
构造函数不确定性的验证
若不同构造函数的参数为父子关系,则会出现相似度一样的两个构造器,这里 Spring 再做了一次验证。 -
实例化 bean
instantiateBean
该函数针对没有参数的构造函数进行处理,首先还是先看看源码。
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
}
else {
// 直接实例化就好了
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
可以发现,该函数直接就开始实例化 bean,相比于 autowireConstructor 少了构造函数的匹配,简单的许多。
实例化策略(InstantiationStrategy)
实例化可以简单地直接用反射,但是 Spring 没有这样做。
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// 如果没有需要覆盖或者动态替换的方法,就不需要使用 CGLIB 进行动态代理
// 因为可以在创建代理的同时将动态方法织入类中,但是若没有需要动态改变方法的地方,直接反射就行
// Don't override the class with CGLIB if no overrides.
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
这里主要是对使用反射还是 cglib 动态代理进行了选择,如果类中没有需要动态改变的方法,即没有使用 replace 或者 lookup 的配置方法,就可以直接使用反射。