死磕Spring之IoC篇 - Bean 的实例化阶段

该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读

Spring 版本:5.1.14.RELEASE

开始阅读这一系列文章之前,建议先查看《深入了解 Spring IoC(面试题)》这一篇文章

该系列其他文章请查看:《死磕 Spring 之 IoC 篇 - 文章导读》

Bean 的实例化阶段

当我们显示或者隐式地调用AbstractBeanFactorygetBean(...) 方法时,会触发 Bean 的加载,在《开启 Bean 的加载》文章中分析了整个加载过程。

对于不同作用域的 Bean,底层都会调用 AbstractAutowireCapableBeanFactorycreateBean(...) 方法进行创建,在上一篇《Bean 的创建过程》文章中分析了整个创建过程。在创建 Bean 的过程中,需要先获取其 Class 对象,然后通过构造方法创建一个实例对象(反射机制),再进行后续的属性填充和初始化工作。整个的实例化过程非常复杂,因为需要找到最匹配的构造方法,还需要找到该方法的入参,所以会有各种处理,本文将会分析创建 Bean 过程中的实例化阶段。

回顾

先来回顾一下创建 Bean 过程中实例化阶段对应的代码:

// AbstractAutowireCapableBeanFactory#doCreateBean(...) 方法
// Instantiate the bean.
/**
 * <1> Bean 的实例化阶段,会将 Bean 的实例对象封装成 {@link BeanWrapperImpl} 包装对象
 * BeanWrapperImpl 承担的角色:
 * 1. Bean 实例的包装
 * 2. {@link org.springframework.beans.PropertyAccessor} 属性编辑器
 * 3. {@link org.springframework.beans.PropertyEditorRegistry} 属性编辑器注册表
 * 4. {@link org.springframework.core.convert.ConversionService} 类型转换器(Spring 3+,替换了之前的 TypeConverter)
 */
BeanWrapper instanceWrapper = null;
// <1.1> 如果是单例模式,则先尝试从 `factoryBeanInstanceCache` 缓存中获取实例对象,并从缓存中移除
if (mbd.isSingleton()) {
    instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// <1.2> 使用合适的实例化策略来创建 Bean 的实例:工厂方法、构造函数自动注入、简单初始化
// 主要是将 BeanDefinition 转换为 BeanWrapper 对象
if (instanceWrapper == null) {
    instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// <1.3> 获取包装的实例对象 `bean`
final Object bean = instanceWrapper.getWrappedInstance();
// <1.4> 获取包装的实例对象的类型 `beanType`
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
    mbd.resolvedTargetType = beanType;
}

Bean 的实例化阶段,会将 Bean 的实例对象封装成 BeanWrapperImpl 包装对象,BeanWrapperImpl 承担的角色

  • Bean 实例的包装
  • PropertyAccessor 属性编辑器
  • PropertyEditorRegistry 属性编辑器注册表
  • ConversionService 类型转换器(Spring 3+,替换了之前的 TypeConverter)

如果是单例模式,则先尝试从 factoryBeanInstanceCache 缓存(保存 FactoryBean 类型的对象)中获取实例对象,并从缓存中移除。目前在创建 Bean 的过程中没发现往这个集合中添加缓存,暂时忽略。我们直接看到下面的一步,调用 createBeanInstance(...) 方法来创建一个实例对象,我们进去看看

开启实例对象的创建

createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 方法,创建一个 Bean 的实例对象,如下:

// AbstractAutowireCapableBeanFactory.java
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    // <1> 获取 `beanName` 对应的 Class 对象
    Class<?> beanClass = resolveBeanClass(mbd, beanName);

    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());
    }

    // <2> 如果存在 Supplier 实例化回调接口,则使用给定的回调方法创建一个实例对象
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }

    // <3> 如果配置了 `factory-method` 工厂方法,则调用该方法来创建一个实例对象
    // 通过 @Bean 标注的方法会通过这里进行创建
    if (mbd.getFactoryMethodName() != null) {
        // 这个过程非常复杂,你可以理解为:
        // 找到最匹配的 Method 工厂方法,获取相关参数(依赖注入),然后通过调用该方法返回一个实例对象(反射机制)
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // Shortcut when re-creating the same bean...
    // <4> 判断这个 RootBeanDefinition 的构造方法是否已经被解析出来了
    // 因为找到最匹配的构造方法比较繁琐,找到后会设置到 RootBeanDefinition 中,避免重复这个过程
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) { // 加锁
            // <4.1> 构造方法已经解析出来了
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                // <4.2> 这个构造方法有入参,表示需要先获取到对应的入参(构造器注入)
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }

    // <5> 如果最匹配的构造方法已解析出来
    if (resolved) {
        // <5.1> 如果这个构造方法有入参
        if (autowireNecessary) {
            // 这个过程很复杂,你可以理解为:
            // 找到最匹配的构造方法,这里会拿到已经被解析出来的这个方法,并找到入参(构造器注入),然后调用该方法返回一个实例对象(反射机制)
            return autowireConstructor(beanName, mbd, null, null);
        }
        // <5.2> 否则,没有入参
        else {
            // 直接调用解析出来构造方法,返回一个实例对象(反射机制)
            return instantiateBean(beanName, mbd);
        }
    }

    // Candidate constructors for autowiring?
    // <6> 如果最匹配的构造方法还没开始解析,那么需要找到一个最匹配的构造方法,然后创建一个实例对象

    /**
     * <6.1> 尝试通过 SmartInstantiationAwareBeanPostProcessor 处理器的 determineCandidateConstructors 方法来找到一些合适的构造方法
     * 参考 {@link org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors}
     */
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    // <6.2> 是否满足下面其中一个条件
    if (ctors != null // 上一步找到了合适的构造方法
            || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR // 构造器注入
            || mbd.hasConstructorArgumentValues() // 定义了构造方法的入参
            || !ObjectUtils.isEmpty(args)) // 当前方法指定了入参
    {
        // 找到最匹配的构造方法,如果 `ctors` 不为空,会从这里面找一个最匹配的,
        // 并找到入参(构造器注入),然后调用该方法返回一个实例对象(反射机制)
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // Preferred constructors for default construction?
    /**
     * <7> 如果第 `6` 步还不满足,那么尝试获取优先的构造方法
     * 参考 {@link org.springframework.context.support.GenericApplicationContext.ClassDerivedBeanDefinition}
     */
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        // <7.1> 如果存在优先的构造方法,则从里面找到最匹配的一个,并找到入参(构造器注入),然后调用该方法返回一个实例对象(反射机制)
        return autowireConstructor(beanName, mbd, ctors, null);
    }

    // No special handling: simply use no-arg constructor.
    // <8> 如果上面多种情况都不满足,那只能使用兜底方法了,直接调用默认构造方法返回一个实例对象(反射机制)
    return instantiateBean(beanName, mbd);
}

过程大致如下:

  1. 获取 beanName 对应的 Class 对象

  2. 如果存在 Supplier 实例化回调接口,则使用给定的回调方法创建一个实例对象,调用 obtainFromSupplier(...) 方法创建

  3. 如果配置了 factory-method 工厂方法,则调用该方法来创建一个实例对象,通过 @Bean 标注的方法会通过这里进行创建,调用 instantiateUsingFactoryMethod(...) 方法创建


如果上面两种情况都不是,那么就进行接下来正常创建 Bean 实例的一个过程

  1. 判断这个 RootBeanDefinition 的构造方法是否已经被解析出来了,因为找到最匹配的构造方法比较繁琐,找到后会设置到 RootBeanDefinition 中,避免重复这个过程

    1. RootBeanDefinition 的 resolvedConstructorOrFactoryMethod 是否不为空,不为空表示构造方法已经解析出来了
    2. 构造方法已经解析出来了,则判断它的 constructorArgumentsResolved 是否不为空,不为空表示有入参,需要先获取到对应的入参(构造器注入)
  2. 如果最匹配的构造方法已解析出来

    1. 如果这个构造方法有入参,则找到最匹配的构造方法,这里会拿到已经被解析出来的这个方法,并找到入参(构造器注入),然后调用该方法返回一个实例对象(反射机制),调用 autowireConstructor(...) 方法创建
    2. 否则,没有入参,直接调用解析出来构造方法,返回一个实例对象(反射机制),调用 instantiateBean(...) 方法创建
  3. 如果最匹配的构造方法还没开始解析,那么需要找到一个最匹配的构造方法,然后创建一个实例对象

    1. 先尝试通过 SmartInstantiationAwareBeanPostProcessor 处理器找到一些合适的构造方法,保存在 ctors

    2. 是否满足下面其中一个条件:ctors 不为空、构造器注入模式、定义了构造方法的入参、当前方法指定了入参,

      则找到最匹配的构造方法,如果 ctors 不为空,会从这里面找一个最匹配的,并找到入参(构造器注入),然后调用该方法返回一个实例对象(反射机制),调用 autowireConstructor(...) 方法创建

  4. 如果第 6 步还不满足,那么尝试从 RootBeanDefinition 中获取优先的构造方法

    1. 如果存在优先的构造方法,则从里面找到最匹配的一个,并找到入参(构造器注入),然后调用该方法返回一个实例对象(反射机制),调用 autowireConstructor(...) 方法创建
  5. 如果上面多种情况都不满足,那只能使用兜底方法了,直接调用默认构造方法返回一个实例对象(反射机制),调用 instantiateBean(...) 方法创建


整个的实例化过程非常的复杂,主要分为以下几种情况:

  1. 指定了 Supplier 实例化回调接口,则回调该接口,返回一个实例对象
  2. 配置了 factory-method 工厂方法创建当前 Bean,则找到这个方法,然后创建一个实例对象(@Bean 注解底层原理也是这种方式)
  3. 找到一个最匹配的构造方法,返回一个实例对象,这个构造方法会设置到这个 RootBeanDefinition 中,避免再次解析,提高性能
  4. 兜底方法,使用默认构造方法返回一个实例对象

这四种情况,其实就分别对应上面四个加粗的方法,接下来依次分析这四个方法

obtainFromSupplier 方法

obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) 方法,通过 Supplier 回调接口获取一个实例对象,方法如下:

// AbstractAutowireCapableBeanFactory.java
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
    Object instance;

    // 获得原当前线程正在创建的 Bean 的名称
    String outerBean = this.currentlyCreatedBean.get();
    // 设置当前线程正在创建的 Bean 的名称
    this.currentlyCreatedBean.set(beanName);
    try {
        // <1> 调用 Supplier 的 get(),返回一个实例对象
        instance = instanceSupplier.get();
    }
    finally {
        if (outerBean != null) {
            // 设置原当前线程正在创建的 Bean 的名称到当前线程变量中
            this.currentlyCreatedBean.set(outerBean);
        }
        else {
            this.currentlyCreatedBean.remove();
        }
    }

    // 未创建 Bean 对象,则创建 NullBean 空对象
    if (instance == null) {
        instance = new NullBean();
    }
    // <2> 将实例对象封装成 BeanWrapper 对象
    BeanWrapper bw = new BeanWrapperImpl(instance);
    // <3> 初始化这个 BeanWrapper 对象
    initBeanWrapper(bw);
    return bw;
}

过程如下:

  1. 调用 Supplier 接口的 get(),返回 instance 实例对象
  2. instance 封装成 BeanWrapper 对象 bw
  3. bw 进行初始化,设置 ConversionService 类型转换器,并注册自定义的属性编辑器

整个过程比较简单

instantiateUsingFactoryMethod 方法

通过 factoryMethodName 工厂方法创建一个实例对象,例如 XML 配置的 factory-method 属性或者 @Bean 标注的方法都会解析成 factoryMethodName 属性

这个过程非常复杂,你可以理解为去找到最匹配的 Method 工厂方法,获取相关入参(依赖注入),然后调用该方法返回一个实例对象(反射机制),方法如下:

// AbstractAutowireCapableBeanFactory.java
protected BeanWrapper instantiateUsingFactoryMethod(
        String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}

创建 ConstructorResolver 对象,然后调用其 instantiateUsingFactoryMethod(...) 方法,如下:

// ConstructorResolver.java
public BeanWrapper instantiateUsingFactoryMethod(
        String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

    // 构造 BeanWrapperImpl 对象
    BeanWrapperImpl bw = new BeanWrapperImpl();
    // 初始化 BeanWrapperImpl,设置 ConversionService 类型转换器,并注册自定义的属性编辑器
    this.beanFactory.initBeanWrapper(bw);

    // -------------------------获取工厂方法的相关信息-------------------------
    // <1> 获取工厂方法的相关信息

    // 工厂方法所在类对应的 Bean(静态方法不会有)
    Object factoryBean;
    // 工厂方法所在类的 Class 对象
    Class<?> factoryClass;
    // 是否为 static 修饰的静态方法
    boolean isStatic;

    // 获取工厂方法所在类对应的 Bean 的名称(静态方法不会有)
    String factoryBeanName = mbd.getFactoryBeanName();
    // <1.1> 非静态方法
    if (factoryBeanName != null) {
        if (factoryBeanName.equals(beanName)) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                    "factory-bean reference points back to the same bean definition");
        }
        // 获取工厂方法所在类对应的 Bean,不然无法调用工厂方法
        factoryBean = this.beanFactory.getBean(factoryBeanName);
        // 如果是单例模式,已经存在对应的 Bean,则抛出重复创建的异常
        if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
            throw new ImplicitlyAppearedSingletonException();
        }
        factoryClass = factoryBean.getClass();
        isStatic = false;
    }
    // <1.2> 静态方法
    else {
        // It's a static factory method on the bean class.
        // 静态方法没有找到对应的 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;
    }

    // -------------------------尝试获取工厂方法对象和入参-------------------------
    // <2> 尝试获取工厂方法对象和参数

    // 工厂方法对象
    Method factoryMethodToUse = null;
    ArgumentsHolder argsHolderToUse = null;
    // 方法参数
    Object[] argsToUse = null;

    // <2.1> 如果方法入参指定了参数,则直接使用
    if (explicitArgs != null) {
        argsToUse = explicitArgs;
    }
    // <2.2> 否则,尝试从 RootBeanDefinition 中获取已解析出来的工厂方法和入参
    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) {
                    // 没有解析过的参数,则尝试从 RootBeanDefinition 中获取未被解析过的参数
                    argsToResolve = mbd.preparedConstructorArguments;
                }
            }
        }
        // 如果获取到了未被解析过的入参,则进行解析
        if (argsToResolve != null) {
            // 处理参数值,类型转换,例如给定方法 A(int, int),配置了 A("1"、"2") 两个参数,则会转换为 A(1, 1)
            argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
        }
    }

    // -------------------------找到所有匹配的工厂方法-------------------------
    // <3> 如果上一步没有找到工厂方法对象或方法入参集合,则需要进行接下来的解析过程,首先找到所有匹配的工厂方法

    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.
        // <3.1> 获取工厂方法所在的类的实例 Class 对象,因为可能是 Cglib 提升过的子类
        factoryClass = ClassUtils.getUserClass(factoryClass);

        // <3.2> 获取工厂方法所在的类中所有方法对象
        Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
        // <3.3> 找到这个类中匹配的工厂方法
        List<Method> candidateList = new ArrayList<>();
        for (Method candidate : rawCandidates) {
            if (Modifier.isStatic(candidate.getModifiers()) == isStatic // 是否和 `isStatic` 匹配
                    && mbd.isFactoryMethod(candidate)) { // 和定义的工厂方法的名称是否相等
                candidateList.add(candidate);
            }
        }

        // <3.4> 如果只有一个匹配的方法,且这个方法没有给指定的入参,且本身也没有定义参数,且这个方法没有定义入参
        // 则直接调用这个方法创建一个实例对象(反射机制),并返回
        if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
            Method uniqueCandidate = candidateList.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;
            }
        }

        // -------------------------开始找最匹配的工厂方法-------------------------
        // <4> 开始找最匹配的工厂方法

        // 将匹配的工厂方法转换成数组
        Method[] candidates = candidateList.toArray(new Method[0]);
        // 将匹配的方法进行排序,public 方法优先,入参个数多的优先
        AutowireUtils.sortFactoryMethods(candidates);

        // 用于承载解析后的方法参数值
        ConstructorArgumentValues resolvedValues = null;
        // 是否是构造器注入
        boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
        int minTypeDiffWeight = Integer.MAX_VALUE;
        // 匹配方法的集合
        Set<Method> ambiguousFactoryMethods = null;

        // -------------------------确定方法参数的入参数量-------------------------
        // <5> 确定方法参数的入参数量,匹配的方法的入参数量要多余它
        // 方法的参数数量的最小值
        int minNrOfArgs;
        // <5.1> 如果当前方法指定了入参,则使用其个数作为最小值
        if (explicitArgs != null) {
            minNrOfArgs = explicitArgs.length;
        }
        // <5.1> 否则,从 RootBeanDefinition 解析出方法的参数个数作为最小值
        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.
            // RootBeanDefinition 定义了参数值
            if (mbd.hasConstructorArgumentValues()) {
                // 方法的参数
                ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
                resolvedValues = new ConstructorArgumentValues();
                // 解析定义的参数值,放入 `resolvedValues` 中,并返回参数个数
                minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
            }
            else {
                minNrOfArgs = 0;
            }
        }

        // 记录 UnsatisfiedDependencyException 异常的集合
        LinkedList<UnsatisfiedDependencyException> causes = null;

        // 遍历匹配的方法
        for (Method candidate : candidates) {
            // 方法体的参数
            Class<?>[] paramTypes = candidate.getParameterTypes();

            if (paramTypes.length >= minNrOfArgs) {
                // -------------------------解析出工厂方法的入参-------------------------
                // <6> 解析出工厂方法的入参

                // 保存参数的对象
                ArgumentsHolder argsHolder;

                // <6.1> 如果当前方法指定了入参,则直接使用
                if (explicitArgs != null) {
                    // Explicit arguments given -> arguments length must match exactly.
                    // 显示给定参数,参数长度必须完全匹配
                    if (paramTypes.length != explicitArgs.length) {
                        continue;
                    }
                    // 根据参数创建参数持有者 ArgumentsHolder 对象
                    argsHolder = new ArgumentsHolder(explicitArgs);
                }
                // <6.2> 否则,通过**依赖注入**获取入参
                else {
                    // Resolved constructor arguments: type conversion and/or autowiring necessary.
                    // 为提供参数,解析构造参数
                    try {
                        String[] paramNames = null;
                        // 获取 ParameterNameDiscoverer 参数名称探测器
                        ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                        // 获取方法的参数名称
                        if (pnd != null) {
                            paramNames = pnd.getParameterNames(candidate);
                        }
                        // 解析出方法的入参,参数值会被依赖注入
                        argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
                                paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
                    }
                    catch (UnsatisfiedDependencyException ex) {
                        // 若发生 UnsatisfiedDependencyException 异常,添加到 causes 中。
                        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;
                    }
                }

                // -------------------------根据权重获取最匹配的方法-------------------------
                // <7> 因为会遍历所有匹配的方法,所以需要进行权重的判断,拿到最优先的那个

                // 判断解析构造函数的时候是否以宽松模式还是严格模式,默认为 true
                // 严格模式:解析构造函数时,必须所有的都需要匹配,否则抛出异常
                // 宽松模式:使用具有"最接近的模式"进行匹配
                // typeDiffWeight:类型差异权重
                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);
                }
            }
        }

        // <8> 没有找到对应的工厂方法,则抛出异常
        if (factoryMethodToUse == 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: " +
                    (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() +
                    "': needs to have a non-void return type!");
        }
        else if (ambiguousFactoryMethods != null) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Ambiguous factory method matches found in bean '" + beanName + "' " +
                    "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
                    ambiguousFactoryMethods);
        }

        // <9> 将解析出来的工厂方法和入参缓存,设置到 RootBeanDefinition 中,因为整个过程比较复杂,避免再次解析
        if (explicitArgs == null && argsHolderToUse != null) {
            mbd.factoryMethodToIntrospect = factoryMethodToUse;
            argsHolderToUse.storeCache(mbd, factoryMethodToUse);
        }
    }

    Assert.state(argsToUse != null, "Unresolved factory method arguments");
     // <10> 调用工厂方法创建一个实例对象(反射机制),并设置到 `bw` 中
    bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
    return bw;
}

这个方法我真的是吐了😢,也太长了吧,硬着头皮看完了一部分,参考文件:ConstructorResolver.java

对于过程不感兴趣的可以跳过直接看下面的概括,过程大致如下:

先创建一个 BeanWrapperImpl 对象 bw,并初始化,设置 ConversionService 类型转换器,并注册自定义的属性编辑器


  1. 获取工厂方法的相关信息,根据 RootBeanDefinition 的 factoryBeanName 属性判断是否静态方法,这个属性表示这个工厂方法所在类对应 Bean 的名称,当然静态方法“不属于”这个 Bean,所以它的这个属性为空
    1. factoryBeanName 属性不为空,表示不是静态方法,则需要根据 factoryBeanName 找到(依赖查找)对应的 Bean,作为 factoryBean
    2. 否则,就是静态方法,获取所在类的 Class 对象即可

这一步找到了三个对象:factoryBean(工厂方法所在类对应的 Bean,静态方法不会有)、factoryClass(工厂方法所在类的 Class 对象)、isStatic(是否为静态方法)。所以想要通过工厂方法获取一个 Bean,则需要方法所在类对应的 Bean 先初始化,然后才能调用这个方法创建 Bean;而静态方法就不用,因为它可以根据所在类的 Class 对象就能调用这个方法创建 Bean,这就是两者的区别。


  1. 尝试获取工厂方法 Method 对象和入参

    1. 如果方法入参指定了参数,则直接使用

    2. 否则,尝试从 RootBeanDefinition 中获取已解析出来的工厂方法和入参,如果获取到了未被解析过的入参,则进行解析(类型转换)

      例如给定方法 A(int, int),配置了 A("1"、"2") 两个参数,则会转换为 A(1, 1)

这一步尝试获取两个对象:factoryMethodToUse(对应的工厂方法 Method)、argsToUse(工厂方法的入参集合)


  1. 如果上一步没有找到工厂方法对象或方法入参集合,找到所有匹配的工厂方法,首先找到所有匹配的工厂方法
    1. 获取工厂方法所在的类的实例 Class 对象,因为可能是 Cglib 提升过的子类
    2. 获取工厂方法所在的类中所有方法对象
    3. 找到这个类中匹配的工厂方法,是否和 isStatic 匹配,并且和定义的工厂方法的名称是否相等
    4. 如果只有一个匹配的方法,且这个方法没有给指定的入参,且本身也没有定义参数,且这个方法没有定义入参,则直接调用这个方法创建一个实例对象(反射机制),并返回

上面第 3.3 步找到的通常只有一个,如果没有入参则可以直接进入第 3.4 步,使用这个方法创建一个实例对象。不过你可能定义了重载方法,也可能定义了方法参数,所以需要进行接下来的解析过程


  1. 开始找最匹配的工厂方法,先排序,public 方法优先,入参个数多的优先
  2. 确定方法参数的入参数量,匹配的方法的入参数量要多余它
    1. 如果当前方法指定了入参,则使用其个数作为最小值
    2. 否则,从 RootBeanDefinition 解析出方法的参数个数作为最小值,没有定义则设置为 0

这一步主要是确定入参的个数,并排序所有匹配的方法,接下来会遍历所有匹配的方法


  1. 解析出工厂方法的入参
    1. 如果当前方法指定了入参,则直接使用
    2. 否则,通过依赖注入获取入参

这一步会找到这个方法的入参,依赖注入的方式


  1. 因为会遍历所有匹配的方法,所以需要进行权重的判断,拿到最优先的那个

通常情况下,我们只有一个匹配的方法,如果存在多个,会根据方法的参数类型进行权重


  1. 没有找到对应的工厂方法,则抛出异常
  2. 将解析出来的工厂方法和入参缓存,设置到 RootBeanDefinition 中,因为整个过程比较复杂,避免再次解析

会缓存这几个数据:resolvedConstructorOrFactoryMethod(已经解析出来的工厂方法)、constructorArgumentsResolved(方法入参已经解析出来了 true)、resolvedConstructorArguments(解析出来的入参)


  1. 调用工厂方法创建一个实例对象(反射机制),并设置到 bw

上面整个过程非常复杂,这里进行简单概括

  • 找到对应的工厂方法,如果是非静态方法,则需要先依赖查找到所在类对应的 Bean,因为需要根据这个 Bean 去调用对应的工厂方法,而静态方法不用,可以根据其 Class 对象调用对应的工厂方法

  • 如果工厂方法有入参,则需要注入相关对象(依赖注入

  • 调用这个方法(反射机制),返回一个实例对象

autowireConstructor 方法

这个过程和上一个方法一样非常复杂,不过差不太多,你可以理解为去找到当前 Bean 的构造方法,获取相关入参(构造器注入),然后调用该构造方法返回一个实例对象(反射机制),方法如下:

// AbstractAutowireCapableBeanFactory.java
protected BeanWrapper autowireConstructor(
        String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
    return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}

创建 ConstructorResolver 对象,然后调用其 autowireConstructor(...) 方法,如下:

// ConstructorResolver.java
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
        @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {

    // 构造 BeanWrapperImpl 对象
    BeanWrapperImpl bw = new BeanWrapperImpl();
    // 初始化 BeanWrapperImpl,设置 ConversionService 类型转换器,并注册自定义的属性编辑器
    this.beanFactory.initBeanWrapper(bw);

    // -------------------------尝试获取构造方法和入参-------------------------
    // <1> 尝试获取构造方法和入参

    // 构造方法
    Constructor<?> constructorToUse = null;
    ArgumentsHolder argsHolderToUse = null;
    // 构造方法的入参集合
    Object[] argsToUse = null;

    // <1.1> 如果当前方法入参指定了参数,则直接使用
    if (explicitArgs != null) {
        argsToUse = explicitArgs;
    }
    // <1.2> 否则,尝试从 RootBeanDefinition 中获取已解析出来的构造方法和入参
    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) {
                    // 没有解析过的参数,则尝试从 RootBeanDefinition(合并后)中获取未被解析过的参数
                    argsToResolve = mbd.preparedConstructorArguments;
                }
            }
        }
        // 如果获取到了未被解析过的入参
        if (argsToResolve != null) {
            // 处理参数值,类型转换,例如给定方法 A(int, int),配配置了 A("1"、"2") 两个参数,则会转换为 A(1, 1)
            argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
        }
    }

    // -------------------------开始获取构造方法和入参-------------------------
    // <2> 如果上一步没有找到构造方法或入参集合,找到所有匹配的工厂方法,首先找到所有匹配的构造方法

    if (constructorToUse == null || argsToUse == null) {
        // Take specified constructors, if any.
        // <2.1> 获取所有的构造方法,如果当前方法指定了构造方法的集合,则使用这个集合
        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);
            }
        }

        // <2.2> 如果构造方法只有一个,且当前方法的入参没有指定参数,且本身也没有定义参数,且这个构造方法没有定义入参
        // 则直接调用这个构造方法创建一个实例对象(反射机制),并返回
        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;

        // -------------------------确定构造方法的入参数量-------------------------
        // <3> 确定构造参数的入参数量,匹配的方法的入参数量要多余它
        // 方法的参数数量的最小值
        int minNrOfArgs;
        if (explicitArgs != null) {
            minNrOfArgs = explicitArgs.length;
        }
        // 从 RootBeanDefinition 解析出方法的参数个数作为最小值
        else {
            ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
            resolvedValues = new ConstructorArgumentValues();
            minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
        }

        // <4> 将所有的构造方法进行排序,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;
            }

            // -------------------------解析出构造方法的入参-------------------------
            // <5> 解析出构造方法的入参

            // 保存参数的对象
            ArgumentsHolder argsHolder;
            // <5.2> 通过**依赖注入**获取入参
            if (resolvedValues != null) {
                try {
                    // 获取构造方法的参数名称(@ConstructorProperties 注解)
                    String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
                    if (paramNames == null) {
                        // 没有获取到则通过 ParameterNameDiscoverer 参数探测器获取参数名称
                        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;
                }
            }
            // <5.1> 如果当前方法的入参指定了参数,如果个数相等则直接使用
            else {
                // Explicit arguments given -> arguments length must match exactly.
                if (paramTypes.length != explicitArgs.length) {
                    continue;
                }
                argsHolder = new ArgumentsHolder(explicitArgs);
            }

            // -------------------------根据权重获取最匹配的方法-------------------------
            // <6> 因为会遍历所有匹配的方法,所以需要进行权重的判断,拿到最优先的那个

            // 判断解析构造函数的时候是否以宽松模式还是严格模式,默认为 true
            // 严格模式:解析构造函数时,必须所有的都需要匹配,否则抛出异常
            // 宽松模式:使用具有"最接近的模式"进行匹配
            // typeDiffWeight:类型差异权重
            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);
            }
        }

        // <7> 没有找到对应的构造方法,则抛出异常
        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);
        }

        // <8> 将解析出来的工厂方法和入参缓存,设置到 RootBeanDefinition 中,因为整个过程比较复杂,避免再次解析
        if (explicitArgs == null && argsHolderToUse != null) {
            argsHolderToUse.storeCache(mbd, constructorToUse);
        }
    }

    Assert.state(argsToUse != null, "Unresolved constructor arguments");
    // <9> 调用这个构造方法返回一个实例对象(反射机制),并设置到 `bw` 中
    bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
    return bw;
}

这个方法我也是吐了😢,不过还好,和上一个方法逻辑差不多,硬着头皮,参考文件:ConstructorResolver.java

对于过程不感兴趣的可以跳过直接看下面的概括,过程大致如下:

先创建一个 BeanWrapperImpl 对象 bw,并初始化,设置 ConversionService 类型转换器,并注册自定义的属性编辑器


  1. 尝试获取构造方法和入参

    1. 如果当前方法入参指定了参数,则直接使用

    2. 否则,尝试从 RootBeanDefinition 中获取已解析出来的构造方法和入参,如果获取到了未被解析过的入参,则进行解析(类型转换)

      例如给定方法 A(int, int),配置了 A("1"、"2") 两个参数,则会转换为 A(1, 1)

这一步尝试获取两个对象:constructorToUse(构造方法)、argsToUse(构造方法的入参集合)


  1. 如果上一步没有找到构造方法或入参集合,找到所有匹配的工厂方法,首先找到所有匹配的构造方法

    1. 获取所有的构造方法,如果当前方法指定了构造方法的集合,则使用这个集合

    2. 如果构造方法只有一个,且当前方法的入参没有指定参数,且本身也没有定义参数,且这个构造方法没有定义入参

      则直接调用这个构造方法创建一个实例对象(反射机制),并返回

上面第 2.2 步,通常只有默认构造方法才会直接调用并返回的,否则需要进行接下来的解析过程


  1. 确定构造参数的入参数量,匹配的方法的入参数量要多余它
  2. 将所有的构造方法进行排序,public 方法优先,入参个数多的优先

这一步主要是确定入参的个数,并排序所有匹配的构造方法,接下来会遍历所有匹配的构造方法


如果前面已经找到匹配的构造方法和入参,则直接结束循环;如果这个构造方法的参数个数小于入参数量,则跳过

  1. 解析出构造方法的入参
    1. 如果当前方法的入参指定了参数,如果个数相等则直接使用
    2. 否则,通过构造器注入获取入参

这一步会找到这个构造方法的入参,构造器注入的方式


  1. 因为会遍历所有匹配的方法,所以需要进行权重的判断,拿到最优先的那个,会根据方法的参数类型进行权重

  1. 没有找到对应的构造方法,则抛出异常
  2. 将解析出来的工厂方法和入参缓存,设置到 RootBeanDefinition 中,因为整个过程比较复杂,避免再次解析

会缓存这几个数据:resolvedConstructorOrFactoryMethod(已经解析出来的构造方法)、constructorArgumentsResolved(方法入参已经解析出来了 true)、resolvedConstructorArguments(解析出来的入参)


  1. 调用这个构造方法返回一个实例对象(反射机制),并设置到 bw

上面整个过程非常复杂,这里进行简单概括

  • 找到最匹配的构造方法

  • 如果构造方法有入参,则需要注入相关对象(构造器注入,其实也是依赖注入获取到的参数)

  • 调用这个构造方法(反射机制),返回一个实例对象

instantiateBean 方法

兜底方法,如果构造方法找不到(或者已经解析出来的构造方法),则直接使用默认的构造方法(或者已经解析出来的构造方法),返回一个实例对象,方法如下:

// AbstractAutowireCapableBeanFactory.java
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
        Object beanInstance;
        final BeanFactory parent = this;
        // 安全模式
        if (System.getSecurityManager() != null) {
            beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                    // 获得 InstantiationStrategy 对象,并使用它,创建 Bean 对象
                    getInstantiationStrategy().instantiate(mbd, beanName, parent),
                    getAccessControlContext());
        }
        else {
             // 获得 InstantiationStrategy 对象,并使用它,创建 Bean 对象
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
        }
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        initBeanWrapper(bw);
        return bw;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}

可以看到会通过 CglibSubclassingInstantiationStrategy#instantiate(...) 方法创建一个实例对象,该方法如下:

// SimpleInstantiationStrategy.java
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    // Don't override the class with CGLIB if no overrides.
    // <1> 没有 MethodOverride 对象,也就是没有需要覆盖或替换的方法,则直接使用反射机制进行实例化即可
    if (!bd.hasMethodOverrides()) {
        Constructor<?> constructorToUse;
        synchronized (bd.constructorArgumentLock) {
            // <1.1> 尝试从 RootBeanDefinition 获得已经解析出来的构造方法 `resolvedConstructorOrFactoryMethod`
            constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
            // <1.2> 没有解析出来的构造方法,则获取默认的构造方法
            if (constructorToUse == null) {
                final Class<?> clazz = bd.getBeanClass();
                // 如果是接口,抛出 BeanInstantiationException 异常
                if (clazz.isInterface()) {
                    throw new BeanInstantiationException(clazz, "Specified class is an interface");
                }
                try {
                    // 从 clazz 中,获得构造方法
                    if (System.getSecurityManager() != null) { // 安全模式
                        constructorToUse = AccessController.doPrivileged(
                                (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
                    }
                    else {
                        constructorToUse = clazz.getDeclaredConstructor();
                    }
                    // 标记 resolvedConstructorOrFactoryMethod 属性
                    bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                }
                catch (Throwable ex) {
                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                }
            }
        }
        // <1.3> 通过这个构造方法实例化一个对象(反射机制)
        return BeanUtils.instantiateClass(constructorToUse);
    }
    // <2> 否则,通过 CGLIB 生成一个子类对象
    else {
        // Must generate CGLIB subclass.
        return instantiateWithMethodInjection(bd, beanName, owner);
    }
}

过程大致如下:

  1. 没有 MethodOverride 对象,也就是没有需要覆盖或替换的方法,则直接使用反射机制进行实例化即可
    1. 尝试从 RootBeanDefinition 获得已经解析出来的构造方法 resolvedConstructorOrFactoryMethod
    2. 没有解析出来的构造方法,则获取默认的构造方法
    3. 通过这个构造方法实例化一个对象(反射机制)
  2. 否则,通过 CGLIB 生成一个子类对象,该过程暂时忽略

整个过程并不复杂

总结

当我们显示或者隐式地调用AbstractBeanFactorygetBean(...) 方法时,会触发 Bean 的加载,在《开启 Bean 的加载》文章中分析了整个加载过程。

对于不同作用域的 Bean,底层都会调用 AbstractAutowireCapableBeanFactorycreateBean(...) 方法进行创建,在上一篇《Bean 的创建过程》文章中分析了整个创建过程。在创建 Bean 的过程中,需要先创建一个实例对象,这个过程在实例化阶段完成,主要分为下面几种情况:

  1. 指定了 Supplier 实例化回调接口,则回调该接口,返回一个实例对象
  2. 配置了 factory-method 工厂方法创建当前 Bean,则找到这个方法,如果有入参,则需要找到对应的参数(依赖注入),然后创建一个实例对象(@Bean 注解底层原理也是这种方式)
  3. 找到一个最匹配的构造方法,如果有入参则需要找到对应的参数(构造器注入),返回一个实例对象,这个构造方法会设置到这个 RootBeanDefinition 中,避免再次解析,提高性能
  4. 兜底方法,使用默认构造方法返回一个实例对象
posted @ 2021-03-02 14:23  月圆吖  阅读(1378)  评论(0编辑  收藏  举报