当前位置: 首页 > news >正文

ConstructorResolver

文章目录

    • 源码解析
      • instantiateUsingFactoryMethod方法
      • autowireConstructor 方法

源码解析

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

    // Bean的实例化阶段,会将Bean的实例对象封装成BeanWrapperImpl包装对象
	BeanWrapper instanceWrapper = null;
	// 如果是单例模式,则先尝试从factoryBeanInstanceCache缓存中获取实例对象,并从缓存中移除
	if (mbd.isSingleton()) {
	    instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	
	// 若缓存中没有可用的BeanWrapper,则调用createBeanInstance方法创建Bean实例,将BeanDefinition转换为BeanWrapper对象。
	// 使用合适的实例化策略来创建 Bean 的实例:工厂方法、构造函数自动注入、简单初始化
	if (instanceWrapper == null) {
	    instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	// ...

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

// AbstractAutowireCapableBeanFactory.java
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 从 Bean 定义中解析出 Bean 的 Class 对象。
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
	// ...
    // 如果配置了 factory-method 工厂方法,则调用该方法来创建一个实例对象
    // 通过 @Bean 标注的方法会通过这里进行创建
    if (mbd.getFactoryMethodName() != null) {
        // 这个过程非常复杂,你可以理解为:
        // 找到最匹配的 Method 工厂方法,获取相关参数(依赖注入),然后通过调用该方法返回一个实例对象(反射机制)
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    // ...
}

instantiateUsingFactoryMethod方法

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

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

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

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

class ConstructorResolver {
	// 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();
	    // 非静态方法
	    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;
	    }
	    // 静态方法
	    else {
	        // 静态方法没有找到对应的 Class 对象无法被调用,则抛出异常
	        if (!mbd.hasBeanClass()) {
	            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
	                    "bean definition declares neither a bean class nor a factory-bean reference");
	        }
	        factoryBean = null;
	        factoryClass = mbd.getBeanClass();
	        isStatic = true;
	    }
	
	    // -------------------------尝试获取工厂方法对象和入参-------------------------
	    // 尝试获取工厂方法对象和参数
	
	    // 工厂方法对象
	    Method factoryMethodToUse = null;
	    ArgumentsHolder argsHolderToUse = null;
	    // 方法参数
	    Object[] argsToUse = null;
	
	    // 如果方法入参指定了参数,则直接使用
	    if (explicitArgs != null) {
	        argsToUse = explicitArgs;
	    }
	    // 否则,尝试从 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);
	        }
	    }
	
	    // -------------------------找到所有匹配的工厂方法-------------------------
	    // 如果上一步没有找到工厂方法对象或方法入参集合,则需要进行接下来的解析过程,首先找到所有匹配的工厂方法
	
	    if (factoryMethodToUse == null || argsToUse == null) {
	        // 获取工厂方法所在的类的实例 Class 对象,因为可能是 Cglib 提升过的子类
	        factoryClass = ClassUtils.getUserClass(factoryClass);
	
	        // 获取工厂方法所在的类中所有方法对象
	        Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
	        // 找到这个类中匹配的工厂方法
	        List<Method> candidateList = new ArrayList<>();
	        for (Method candidate : rawCandidates) {
	            if (Modifier.isStatic(candidate.getModifiers()) == isStatic // 是否和 `isStatic` 匹配
	                    && mbd.isFactoryMethod(candidate)) { // 和定义的工厂方法的名称是否相等
	                candidateList.add(candidate);
	            }
	        }
	
	        // 如果只有一个匹配的方法,且这个方法没有给指定的入参,且本身也没有定义参数,且这个方法没有定义入参
	        // 则直接调用这个方法创建一个实例对象(反射机制),并返回
	        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;
	            }
	        }
	
	        // -------------------------开始找最匹配的工厂方法-------------------------
	        // 开始找最匹配的工厂方法
	
	        // 将匹配的工厂方法转换成数组
	        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;
	
	        // -------------------------确定方法参数的入参数量-------------------------
	        // 确定方法参数的入参数量,匹配的方法的入参数量要多余它
	        // 方法的参数数量的最小值
	        int minNrOfArgs;
	        // 如果当前方法指定了入参,则使用其个数作为最小值
	        if (explicitArgs != null) {
	            minNrOfArgs = explicitArgs.length;
	        }
	        // 否则,从 RootBeanDefinition 解析出方法的参数个数作为最小值
	        else {
	            // 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) {
	                // -------------------------解析出工厂方法的入参-------------------------
	                // 解析出工厂方法的入参
	
	                // 保存参数的对象
	                ArgumentsHolder argsHolder;
	
	                // 如果当前方法指定了入参,则直接使用
	                if (explicitArgs != null) {
	                    // Explicit arguments given -> arguments length must match exactly.
	                    // 显示给定参数,参数长度必须完全匹配
	                    if (paramTypes.length != explicitArgs.length) {
	                        continue;
	                    }
	                    // 根据参数创建参数持有者 ArgumentsHolder 对象
	                    argsHolder = new ArgumentsHolder(explicitArgs);
	                }
	                // 否则,通过依赖注入获取入参
	                else {
	                    // 为提供参数,解析构造参数
	                    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);
	                        }
	                        if (causes == null) {
	                            causes = new LinkedList<>();
	                        }
	                        causes.add(ex);
	                        continue;
	                    }
	                }
	
	                // -------------------------根据权重获取最匹配的方法-------------------------
	                // 因为会遍历所有匹配的方法,所以需要进行权重的判断,拿到最优先的那个
	
	                // 判断解析构造函数的时候是否以宽松模式还是严格模式,默认为 true
	                // 严格模式:解析构造函数时,必须所有的都需要匹配,否则抛出异常
	                // 宽松模式:使用具有"最接近的模式"进行匹配
	                // typeDiffWeight:类型差异权重
	                int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
	                        argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
	                // 代表最匹配的结果,则选择作为符合条件的方法
	                if (typeDiffWeight < minTypeDiffWeight) {
	                    factoryMethodToUse = candidate;
	                    argsHolderToUse = argsHolder;
	                    argsToUse = argsHolder.arguments;
	                    minTypeDiffWeight = typeDiffWeight;
	                    ambiguousFactoryMethods = null;
	                }
	                // 如果具有相同参数数量的方法具有相同的类型差异权重,则收集此类型选项
	                // 但是,仅在非宽松构造函数解析模式下执行该检查,并显式忽略重写方法(具有相同的参数签名)
	                else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
	                        !mbd.isLenientConstructorResolution() &&
	                        paramTypes.length == factoryMethodToUse.getParameterCount() &&
	                        !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
	                    // 查找到多个可匹配的方法
	                    if (ambiguousFactoryMethods == null) {
	                        ambiguousFactoryMethods = new LinkedHashSet<>();
	                        ambiguousFactoryMethods.add(factoryMethodToUse);
	                    }
	                    ambiguousFactoryMethods.add(candidate);
	                }
	            }
	        }
	
	        // 没有找到对应的工厂方法,则抛出异常
	        if (factoryMethodToUse == null) {
	            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);
	        }
	
	        // 将解析出来的工厂方法和入参缓存,设置到 RootBeanDefinition 中,因为整个过程比较复杂,避免再次解析
	        if (explicitArgs == null && argsHolderToUse != null) {
	            mbd.factoryMethodToIntrospect = factoryMethodToUse;
	            argsHolderToUse.storeCache(mbd, factoryMethodToUse);
	        }
	    }
	
	    Assert.state(argsToUse != null, "Unresolved factory method arguments");
	     // 调用工厂方法创建一个实例对象(反射机制),并设置到 `bw` 中
	    bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
	    return 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;
}

http://www.dtcms.com/a/113277.html

相关文章:

  • Day2-2:前端项目uniapp壁纸实战
  • HashMap 底层原理详解
  • C++学习之LINUX网络编程-套接字通信基础
  • JWT认证服务
  • [MySQL初阶]MySQL(9)事务机制
  • 基于springboot+vue的二手车交易系统
  • Supervisor的安装和使用
  • 0101安装matplotlib_numpy_pandas-报错-python
  • Business English Certificates (BEC) 高频词汇学习
  • 将MATLAB神经网络数据转换为C/C++进行推理计算
  • Linux网络状态监控利器:netstat与ping命令详解
  • Java的Selenium的特殊元素操作与定位之select下拉框
  • RocketMQ初认识
  • C,C++语言缓冲区溢出的产生和预防
  • 【2012】【论文笔记】太赫兹波在非磁化等离子体——
  • 【国产突围!致远电子ZXDoc如何打破Vector垄断,成为新能源车研发“神器”?】
  • Xshell Plus 6下载与安装
  • 【机器学习】机器学习工程实战-第4章 特征工程
  • LabVIEW商业软件开发注意问题
  • C语言-基础语法学习
  • 【Linux系统】linux下的软件管理
  • 大数据技术发展与应用趋势分析
  • `use_tempaddr` 和 `temp_valid_lft ` 和 `temp_prefered_lft ` 笔记250405
  • web性能检测工具lighthouse
  • k8s 1.23升级1.24
  • JavaSE基础——第六章 类与对象(二)
  • 使用dockerbuildx在x86机器上构建arm版docker镜像
  • 神经网络基础
  • 嵌入式AI简介
  • java面向对象 - 封装、继承和多态