zoukankan      html  css  js  c++  java
  • Spring IoC bean 的创建

    前言

    本系列全部基于 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 实例。

    BeanDefinition 合并后处理

    AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors

    protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof MergedBeanDefinitionPostProcessor) {
                MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
                bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
            }
        }
    }
    

    上面代码很简单,无非就是拿到所有注册的 BeanPostProcessor ,然后遍历判断是否是 MeragedBeanDefinitionPostProcessor 类型,是的话进行 BeanDefinition 合并后的方法回调,在这个回调方法内你可以对指定 beanBeanDefinition 做一些修改。

    下面我们简单看一下 MergedBeanDefinitionPostProcessor 接口中的方法:

    public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
    
        /**
         * 对指定bean的BeanDefinition合并后的处理方法回调
         */
        void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
    
        /**
         * 通知已重新设置指定beanName的BeanDefinition,如果实现该方法应该清除受影响的bean的所有元数据
         * @since 5.1
         */
        default void resetBeanDefinition(String beanName) {
            
        }
    
    }
    

    总结

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

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

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

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

    参考

  • 相关阅读:
    令人恼怒!mount windows共享目录出错
    今天修改PCB板图
    在深圳出差
    触摸屏技术原理介绍
    getrlimit和setrlimit函数
    OpenCV下的HelloWorld
    两本OpenCV的书到了
    GDB用法小结
    没搞懂自适应二进制阈值化的参数
    【JavaScript】73 逆序的三位数 (10分)
  • 原文地址:https://www.cnblogs.com/leisurexi/p/13196998.html
Copyright © 2011-2022 走看看