前言

本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本。因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析。

本篇文章主要介绍 Spring IoC 容器是怎么创建 bean 的实例。

正文

在上一篇Spring IoC bean 的加载中有这么一段代码:

if (mbd.isSingleton()) {
// 创建和注册单例 bean
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建 bean 实例
return createBean(beanName, mbd, args);
}
// 省略异常处理...
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

如果 bean 的作用域是单例,会调用 getSingleton() 方法并传入 beanNameObjectFacoty作为参数;而 getSingleton() 方法会调用 ObjectFactorygetObject() 方法也就是上面代码中的 createBean() 方法,返回 bean

这里的 ObjectFactorybean 的延迟依赖查找接口,定义如下:

@FunctionalInterface
public interface ObjectFactory<T> { T getObject() throws BeansException; }

只有在调用 getObject() 方法时才会真正去获取 bean。下面我们正式开始分析 createBean() 方法。

AbstractAutowireCapableBeanFactory#createBean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {

    RootBeanDefinition mbdToUse = mbd;

    // 将String类型的class字符串,转换为Class对象,例如在XML中配置的class属性
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
} try {
// 进行定义的方法覆盖
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex);
} try {
// 如果bean的实例化前回调方法返回非null,直接返回实例,跳过后面步骤。见下文详解
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex);
} try {
// 真正去创建bean的方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
// 返回bean的实例
return beanInstance;
}
// 省略异常处理...
}

bean 实例化前置处理

我们先看一下 InstantiationAwareBeanPostProcessor 接口的定义:

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    /**
* Bean 实例化前调用,返回非 {@code null} 回调过后面流程
* 返回 {@code null} 则进行 IoC 容器对 Bean 的实例化
*/
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
} /**
* Bean 实例化之后,属性填充之前调用,返回 {@code true} 则进行默认的属性填充步骤,
* 返回 {@code false} 会跳过属性填充阶段,同样也会跳过初始化阶段的生命周期方法的回调。
*/
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
} /**
* Bean 实例化后属性赋值前调用,PropertyValues 是已经封装好的设置的属性值,返回 {@code null} 继续
*/
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return null;
} /**
* 5.1 版本后已经被上面 postProcessProperties 方法所替代,功能与上面方法一样
*/
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
} }

上面接口继承于 BeanPostProcessorBeanPostProcessor 中定义了 bean 的初始化阶段生命周期回调方法,会在后续介绍)提供了三个扩展点,如下:

  • bean 实例化前
  • bean 实例化后
  • bean 属性赋值前

这也是 bean 实例化阶段的生命周期回调方法。

AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// 判断bean在实例化之前是否已经解析过
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// 如果bean是合成的 && 有实现 InstantiationAwareBeanPostProcessor 接口
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 解析bean的类型
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 执行bean的实例化前回调
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
// 如果实例化前生命周期回调方法返回的不是null
if (bean != null) {
// 执行bean的实例化后回调,因为会跳过后续步骤,所以只能在此处调用了
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
// 如果bean不为空,则将beforeInstantiationResolved赋值为true,代表在实例化之前已经解析
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}

创建 bean

AbstractAutowireCapableBeanFactory#doCreateBean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {

    // 实例化 bean
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 如果bean的作用域是singleton,则需要移除未完成的FactoryBean实例的缓存
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 通过构造函数反射创建bean的实例,但是属性并未赋值,见下文详解
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 获取bean的实例
final Object bean = instanceWrapper.getWrappedInstance();
// 获取bean的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
} synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// BeanDefinition 合并后的回调,见下文详解
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
// 省略异常处理...
mbd.postProcessed = true;
}
} // bean的作用域是单例 && 允许循环引用 && 当前bean正在创建中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
// 如果允许bean提前曝光
if (earlySingletonExposure) {
// 将beanName和ObjectFactory形成的key-value对放入singletonFactories缓存中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
} Object exposedObject = bean;
try {
// 给 bean 的属性赋值
populateBean(beanName, mbd, instanceWrapper);
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// 省略异常处理... // 如果允许单例bean提前暴露
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
// 只有在检测到循环依赖的情况下才不为空
if (earlySingletonReference != null) {
// 如果exposedObject没有在初始化方法中被改变,也就是没有被增强
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
// 检测依赖
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
} try {
// 用于注册销毁bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
// 返回bean实例
return exposedObject;
}

创建 bean 的实例

AbstractAutowireCapableBeanFactory#createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 解析 bean 的类型
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 判断beanClass是否是public修饰的类,并且是否允许访问非公共构造函数和方法,不是抛出异常
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// Spring 5新添加的,如果存在Supplier回调,则使用给定的回调方法初始化策略。
// 可以使RootBeanDefinition#setInstanceSupplier()设置
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 如果设置工厂方法则使用给定的方法创建bean实例,这里分为静态工厂和实例化工厂
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
} // 快捷方式创建相同的bean
// resolved: 构造函数或工厂方法是否已经解析过
boolean resolved = false;
// autowireNecessary: 是否需要自动注入 (即是否需要解析构造函数)
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 如果resolvedConstructorOrFactoryMethod不为空,代表构造函数或工厂方法已经解析过
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// 根据constructorArgumentsResolved判断是否需要自动注入
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
// 如果构造函数或工厂方法已经解析过并且需要自动注入,则执行构造器自动注入,见下文详解
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 否则使用默认构造函数进行bean实例化,见下文详解
return instantiateBean(beanName, mbd);
}
} // 调用SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors()方法
// 拿到 bean 的候选构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 候选构造函数不为空 || 构造函数依赖注入 || 定义了构造函数的参数值 || args不为空,则执行构造器自动注入
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
} // 如果有首选的构造函数,使用该构造函数去创建bean实例
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
} // 没有特殊处理,使用默认无参构造器实例化bean
return instantiateBean(beanName, mbd);
}

上面方法主要判断是使用构造函数自动注入,还是使用默认构造函数构造。总结起来以下几种情况会使用构造函数自动注入:

  • 已经缓存过构造函数并且构造函数的参数已经解析过。
  • 候选的构造函数不为空,这里的候选构造函数是通过实现 SmartInstantiationAwareBeanPostProcessor 接口中的 determineCandidateConstructors() 方法
  • 自动注入模式为构造函数自动注入
  • BeanDefinition 定义了构造函数参数,如 XML 中的 <constructor-arg index="0" value="1"/>
  • 在调用 getBean() 方法时显示指定了 args 参数

上面方法中还有一个判断是否有缓存的过程,是因为一个 bean 对应的类中可能会有多个构造函数,而每个构造函数的参数不同,Spring 在根据参数及类型去判断最终会使用哪个构造函数进行实例化。但是,判断的过程是个比较消耗性能的步骤,所以采用缓存机制,如果已经解析过则不需要重复解析而是直接从 RootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 缓存的值去取,否则需要再次解析,并将解析的结果添加至 RootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 中。

这里简单介绍一下 SmartInstantiationAwareBeanPostProcessor 这个接口,它继承于 InstantiationAwareBeanPostProcessor,如下:

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {

    /**
* 预测 bean 的类型
*/
@Nullable
default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
return null;
} /**
* 选择合适的构造器,比如目标对象有多个构造器,在这里可以进行一些定制化,选择合适的构造器
*/
@Nullable
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
return null;
} /**
* 获得提前暴露的 bean 引用,主要用于解决循环引用的问题
* 只有单例对象才会调用此方法
*/
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
return bean;
} }

其实我们熟知的 @Autowired 注解标注在构造函数上实现自动注入,也是重写了该接口的 determineCandidateConstructors() 方法实现的。

默认无参构造器实例化 bean

AbstractAutowireCapableBeanFactory#instantiateBean

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
// 使用指定的策略去实力化bean
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
// 将实例化后的bean封装成BeanWrapper后返回
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
// 省略异常处理...
} // SimpleInstantiationStrategy.java
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// 如果有需要覆盖或者动态替换的方法则当然需要使用CGLIB进行动态代理,因为可以在创建代理的同时将方法织入类中
// 但是如果没有需要动态改变的方法,为了方便直接用反射就可以了
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
// 获取缓存的构造方法或工厂方法
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
// 缓存为空
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
// 如果clazz是接口,抛出异常
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
// 获取默认的无参构造函数
constructorToUse = clazz.getDeclaredConstructor();
// 设置缓存
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 这里就是用指定的无参构造器去实例化该bean,不做具体分析了
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// 用CGLIB生成子类动态织入重写的方法
return instantiateWithMethodInjection(bd, beanName, owner);
}
}

寻找合适的构造器实例化 bean

ConstructorResolver#autowireConstructor

protected BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
// 寻找适合的构造器,进行实例化
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
} public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) { BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
// 最终实例化的构造函数
Constructor<?> constructorToUse = null;
// 最终用于实例化的参数Holder
ArgumentsHolder argsHolderToUse = null;
// 最终用于实例化的构造函数参数
Object[] argsToUse = null;
// 如果explicitArgs不为空,则使用explicitArgs当做构造器函数参数
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
// 获取已经缓存的构造函数或工厂方法
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// 获取已经缓存的构造函数参数
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
// 如果已经缓存了构造函数或工厂方法,
// 那么resolvedConstructorArguments和preparedConstructorArguments必定有一个缓存了构造函数参数
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
// 如果argsToResolve不为空,则对构造函数参数进行解析,也就是会进行类型转换之类的操作
// 例如 A(int,int),把配置中的 ("1","1") 转换为 (1,1)
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
// 如果没有缓存构造函数或者其参数
if (constructorToUse == null || argsToUse == null) {
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
// 如果允许访问非public的构造函数和方法(该值默认为 true),就获取所有构造函数,否则只获取public修饰的构造函数
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);
}
}
// 如果只有一个构造函数 && getBean()没有显示指定args && 没有定义构造函数的参数值
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;
}
// 通过无参构造函数创建bean的实例,然后直接返回
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
} // 如果候选构造函数不为空 || 构造函数自动注入模式
boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null; int minNrOfArgs;
// getBean()显示指定了参数,获取参数长度
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// 获取定义的构造函数参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
// 解析构造函数参数并赋值到resolvedValues,返回参数个数。见下文详解
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) {
// 获取参数数量
int parameterCount = candidate.getParameterCount();
// 如果已经找到满足的构造函数 && 目标构造函数参数个数大于当前遍历的构造函数参数个数则终止
// 因为构造函数已经是排过序的,后面不会再有更适合的了
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
break;
}
// 如果目标的构造函数参数个数小于我们需要的,直接跳过
if (parameterCount < minNrOfArgs) {
continue;
} ArgumentsHolder argsHolder;
// 获取到构造函数的参数类型
Class<?>[] paramTypes = candidate.getParameterTypes();
if (resolvedValues != null) {
try {
// 评估参数名称,就是判断构造函数上是否标注了@ConstructorProperties注解,如果标注了,直接取其中定义的参数名称
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
// 没有标注@ConstructorProperties注解,使用参数名称解析器,获取参数名称
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
// 创建一个参数数组以调用构造函数或工厂方法,见下文详解
// 主要是通过参数类型和参数名解析构造函数或工厂方法所需的参数(如果参数是其他bean,则会解析依赖的bean)
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
// Swallow and try next constructor.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
// resolvedValues为空, explicitArgs不为空,即显示指定了getBean()的args参数
else {
// 如果当前构造函数参数个数不等的explicitArgs的长度,直接跳过该构造函数
if (parameterCount != explicitArgs.length) {
continue;
}
// 把explicitArgs封装进ArgumentsHolder
argsHolder = new ArgumentsHolder(explicitArgs);
}
// 根据mbd的解析构造函数模式(true: 宽松模式,false:严格模式)
// 将argsHolder的参数和paramTypes进行比较,计算paramTypes的类型差异权重值
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// 差异值越小代表构造函数越匹配,则选择此构造函数
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
// 如果出现权重值更小的候选者,则将ambiguousConstructors清空,允许之前存在权重值相同的候选者
ambiguousConstructors = null;
}
// 两个候选者权重值相同,并且是当前遍历过权重值最小的
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
// 将两个候选者添加到ambiguousConstructors
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);
}
// getBean()方法没有指定args参数 && 构造函数参数不为空
if (explicitArgs == null && argsHolderToUse != null) {
// 缓存解析过后的构造函数和参数
argsHolderToUse.storeCache(mbd, constructorToUse);
}
} Assert.state(argsToUse != null, "Unresolved constructor arguments");
// 利用反射创建bean实例
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}

上面方法的功能主要如下:

  1. 构造函数参数的确定

    • 如果 explicitArgs 参数不为空,那就可以直接确定参数。因为 explicitArgs 参数是在调用 getBean() 时手动指定的,这个主要用于静态工厂方法的调用。
    • 缓存中不为空,那么可以直接拿过来使用。
    • BeanDefinition 中读取,我们所定义的 bean 都会生成一个 BeanDefinition ,其中记录了定义了构造函数参数通过 getConstructorArgumentValues() 获取。
  2. 构造函数的确定。经过第一步已经确定构造函数的参数,接下来就是用参数个数在所有的构造函数中锁定对应的构造函数。匹配之前会对构造函数进行排序,首先是 public 构造函数且参数个数从多到少,然后是非public 构造函数且参数个数有多到少。这样可以迅速判断排在后面的构造函数参数个数是否符合条件。
  3. 根据对应的构造函数转换对应的参数类型。
  4. 根据实例化策略以及得到的构造函数和构造函数参数实例化 bean

解析构造函数参数

ConstructorResolver#resolveConstructorArguments
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
// 获取自定义类型转换器
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
// 如果没有自定义的转换器就用bw
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
// minNrOfArgs初始化为indexedArgumentValues+genericArgumentValues的个数总和
int minNrOfArgs = cargs.getArgumentCount();
// 遍历IndexArgumentValues,这里的IndexArgumentValues就带下标的,如:<constructor-arg index="0" value="1"/>
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);
}
// 如果index大于minNrOfArgs,修改minNrOfArgs值
if (index > minNrOfArgs) {
// 因为index是构造函数下标值,所以总数这边要加1
minNrOfArgs = index + 1;
}
ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
// 如果参数类型已经转换过,直接添加进resolvedValues
if (valueHolder.isConverted()) {
resolvedValues.addIndexedArgumentValue(index, valueHolder);
}
// 参数类型没有转换过,进行转换
else {
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
// 使用转换过的参数值构建ValueHolder
ConstructorArgumentValues.ValueHolder resolvedValueHolder =
new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
// 添加进resolvedValues
resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
}
}
// 遍历GenericArgumentValues并进行类型转换和上面一样,这里的GenericArgumentValues就是没有指定下标的
// 如:<constructor-arg value="1"/>
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;
}

上面方法主要将 indexedArgumentValuesgenericArgumentValues 属性中的值通过调用 resolveValueIfNecessary() 方法进行解析;resolveValueIfNecessary() 方法主要解析参数的类型,比如 ref 属性引用的 beanName 会通过 getBean() 返回实例。

创建参数数组

ConstructorResolver#createArgumentArray
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
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] : "");
ConstructorArgumentValues.ValueHolder valueHolder = null;
if (resolvedValues != null) {
// 根据参数的下标、类型、名称查询是否有匹配的
valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
// 没有匹配的 && 不是自动装配。尝试下一个通用的无类型参数值作为降级方法
// 它可以在类型转换后匹配 (例如,String -> int)
if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
}
// 找到了匹配的valueHolder
if (valueHolder != null) {
// 添加进usedValueHolders
usedValueHolders.add(valueHolder);
Object originalValue = valueHolder.getValue();
Object convertedValue;
// 类型已经转换过
if (valueHolder.isConverted()) {
// 获取已经转换过的值,作为args在paramIndex的预备参数
convertedValue = valueHolder.getConvertedValue();
args.preparedArguments[paramIndex] = convertedValue;
}
// 类型没有转换过
else {
// 将构造方法和参数下标封装成MethodParameter(MethodParameter是封装方法和参数索引的工具类)
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
try {
// 将原始值转换为paramType类型的值,无法转换时抛出异常
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需要解析
args.resolveNecessary = true;
// 将sourceValue作为args在paramIndex位置的预备参数
args.preparedArguments[paramIndex] = sourceValue;
}
}
// 将convertedValue作为args在paramIndex位置的参数
args.arguments[paramIndex] = convertedValue;
// 将originalValue作为args在paramIndex位置的原始参数
args.rawArguments[paramIndex] = originalValue;
}
// 没有找到匹配的valueHolder
else {
// 将构造方法和参数下标封装成MethodParameter
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
// 找不到明确的匹配,并且不是自动注入,抛出异常
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 {
// 如果是自动注入,用resolveAutowiredArgument()解析参数,见下文详解
// 构造函数自动注入中的参数bean就是在这边处理
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
// 将通过自动装配解析出来的参数赋值给args
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);
}
}
}
// 如果依赖了其他的bean,则注册依赖关系(这边的autowiredBeanNames,就是所有依赖的beanName)
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
}
// 返回解析后的参数值
return args;
}

上面方法判断构造函数如果有匹配的参数会转换成对应类型,如果没有匹配的参数,多半是构造函数自动注入,通过 resolveAutowiredArgument() 去查找 bean 并返回实例。

ConstructorResolver#resolveAutowiredArgument
protected Object resolveAutowiredArgument(MethodParameter param, String beanName, @Nullable Set<String> autowiredBeanNames, TypeConverter typeConverter, boolean fallback) {
// 获取参数的类型
Class<?> paramType = param.getParameterType();
// 如果参数类型是InjectionPoint
if (InjectionPoint.class.isAssignableFrom(paramType)) {
// 拿到当前的InjectionPoint(存储了当前正在解析依赖的方法参数信息,DependencyDescriptor)
InjectionPoint injectionPoint = currentInjectionPoint.get();
if (injectionPoint == null) {
// 当前injectionPoint为空,则抛出异常:目前没有可用的InjectionPoint
throw new IllegalStateException("No current InjectionPoint available for " + param);
}
// 当前injectionPoint不为空,直接返回
return injectionPoint;
}
try {
// 解析指定依赖,DependencyDescriptor:
// 将MethodParameter的方法参数索引信息封装成DependencyDescriptor,见下文详解
return this.beanFactory.resolveDependency(
new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
}
// 忽略异常处理...
}

上面方法中的 resolveDependency() 方法就是解决依赖注入的关键所在,在分析这个方法之前我们先简单看一下 DependencyDescriptor 类。

public class DependencyDescriptor extends InjectionPoint implements Serializable {

    // 包装依赖(属性或者方法的某个参数)所在的声明类
private final Class<?> declaringClass; // 如果所包装依赖是方法的某个参数,则这里记录该方法的名称
@Nullable
private String methodName; // 如果所包装的是方法的某个参数,则这里记录该参数的类型
@Nullable
private Class<?>[] parameterTypes; // 如果所包装的是方法的某个参数,则这里记录该参数在该函数参数列表中的索引
private int parameterIndex; // 如果所包装的是属性,则这里记录该属性的名称
@Nullable
private String fieldName; // 标识所包装依赖是否必要依赖
private final boolean required; // 标识所包装依赖是否需要饥饿加载
private final boolean eager; // 标识所包装依赖的嵌套级别
private int nestingLevel = 1; // 标识所包装依赖的包含者类,通常和声明类是同一个
@Nullable
private Class<?> containingClass; // 省略其他代码... }

这个类就是依赖描述符,存储了需要注入 bean 的类型、构造器参数的下标(构造器注入该值不为空)、是否必需、字段名称(字段注入该值不为空)、方法名称(set 方法注入该值不为空)等。

依赖解决

DefaultListableBeanFactory#resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// Optional类型的处理,说明Spring也可以注入Optional类型的参数
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
// ObjectFactory或ObjectProvider类型的处理
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
// javax.inject.Provider类型的处理
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
// 获取延迟解析代理
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// 解析依赖,返回的result为最终需要注入的bean实例,见下文详解
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 获取需要注入bean的快捷方式,不为空直接返回
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 获取需要注入bean的类型
Class<?> type = descriptor.getDependencyType();
// 用于支持Spring中新增的注解@Value(确定给定的依赖项是否声明@Value注解,如果有则拿到值)
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// 解析MultipleBean,例如 Array,Collection,Map
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 根据类型找到匹配的bean
// matchingBeans(key: beanName value: 如果bean已经缓存了实例(例如单例bean会缓存其实例),
// 就是bean的实例,否则就是对应的class对象)
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// 没有找到匹配的bean,判断是不是必需的,不是直接返回null,否则抛出异常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
} String autowiredBeanName;
Object instanceCandidate;
// 如果有多个匹配的候选者
if (matchingBeans.size() > 1) {
// 判断最佳的候选者,也就是寻找最匹配的beanName
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
return null;
}
}
// 拿到autowiredBeanName对应的value(bean实例或bean实例类型)
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// 只找到一个符合的bean
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
} if (autowiredBeanNames != null) {
// 将依赖的beanName添加到autowiredBeanNames中
autowiredBeanNames.add(autowiredBeanName);
}
// 如果需要注入的bean没有缓存实例,那么instanceCandidate是一个Class对象,再根据getBean()去获取对应的实例
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
// 返回最终需要注入的bean实例
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}

上面方法才是真正去获取需要注入的 bean,大概分为以下几个步骤:

  1. 查看是否有快捷方式获取注入 bean 是否为空,不为空直接返回。这里的快捷方式是通过继承 DependencyDescriptor 并重写 resolveShortcut() 来实现。

  2. 如果参数使用 @Value 注解修饰了,如果获取到值直接返回。

  3. 解析 MultipleBean,这里的 MultipleBean 一般是 ArrayCollectionMap 这种,不为空直接返回。

  4. 根据类型找到所有匹配的 beanmatchingBeanskeybeanNamevalue 的值有两种情况,如果bean已经缓存了实例(例如单例bean会缓存其实例),就是bean的实例,否则就是对应的class对象)。

  5. matchingBeans 为空,判断需要注入的 bean 是否是必须的,如果是抛出异常,否则返回 null

  6. matchingBeans 长度大于1,代表有多个候选者;选择最佳的候选者,规则是:

    1. 首先查找 primary 属性为 true 的。
    2. 查找优先级最高的,实现 PriorityOrdered 接口或者标注 @Priority 注解的。
    3. 查找名称匹配的。
  7. 只有一个候选者,直接使用。

  8. 如果需要注入的 bean 没有缓存实例,那么 instanceCandidate是一个 Class 对象,再根据 getBean() 方法去获取对应的实例。

  9. 最终返回需要注入的 bean 实例。

总结

本文主要介绍了创建 bean 实例的流程,我们可以重新梳理一下思路:

  1. 进行 bean 的实例化前方法回调,如果返回非空,跳过后面步骤
  2. 创建 bean 的实例,如果是构造函数注入会选择最适合的构造函数进行参数自动注入,否则调用默认的无参构造进行实例化 bean

由于 doCreateBean() 方法中操作太多,这里会分为几篇文章,一一分析各个阶段。

最后,我模仿 Spring 写了一个精简版,代码会持续更新。地址:https://github.com/leisurexi/tiny-spring

参考

最新文章

  1. MR21、MR22和CK24的区别
  2. 用Java写算法之归并排序
  3. Eclipse开发STM32出现找不到函数的情况的解决方法
  4. SQL server 那些数据类型不能作为索引
  5. Xshell
  6. Web开发者选择的最佳HTML5/CSS3代码生成器
  7. 情报收集:Metasploit命令、查询网站和测试网站
  8. TFS Build Error: CSC : fatal error CS0042: Unexpected error creating debug information file &#39;xxxx.PDB&#39;
  9. uva 10330 最大流
  10. Activity Launch Mode
  11. centos7安装mplayer以及出现的各种问题
  12. 设备11g_rac配置对等
  13. C#快速学习
  14. SQL Server 日志清理
  15. 在flask中使用swagger(flasgger使用方法及效果展示)
  16. Logger级别和输出的地方
  17. toString方法的用法
  18. Java基础教程(13)--包
  19. python subprocess 和 multiprocess选择以及我遇到的坑
  20. Arduino-元件简介

热门文章

  1. day08 for循环与字符串掌握操作
  2. Scala - 语言专家 - Desugar Scala code
  3. Chisel3 - util - LFSR16
  4. Java实现 LeetCode 835 图像重叠(暴力)
  5. (Java实现) 洛谷 P1691 有重复元素的排列问题
  6. Java实现 LeetCode 524 通过删除字母匹配到字典里最长单词(又是一道语文题)
  7. Java实现 蓝桥杯VIP 算法提高 Quadratic Equation
  8. Java实现 LeetCode 111 二叉树的最小深度
  9. java实现最大公约数
  10. 循序渐进VUE+Element 前端应用开发(7)--- 介绍一些常规的JS处理函数