Spring核心原理:依赖注入

  1. 依赖注入发生时间

Spring IOC容器完成Bean定义资源的定位,载入和解析注册,IOC容器就可以管理Bean定义的相关数据,但是IOC容器还没有对所管理的Bean进行依赖注入,而依赖注入在以下两种情况下发生:

1.1,用户第一次调用getBean()方法时IOC容器触发依赖注入。

1.2,当用户在配置文件中将<bean>元素配置了Lazy-init=false属性时,即让容器在解析注册Bean定义时进行预实例化,触发依赖注入。

  1. 依赖注入的过程

2.1,getBean()方式依赖注入过程

在Spring当中BeanFactory接口定义类Spring ioc容器的基本功能规范,该接口定义了重载了几个getBean()的方法,用于用户向容器索取Bea,而其由AbstractBeanFactory类进行实现。

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

        // 根据给定的Bean名称获取
    @Override
    public Object getBean(String name) throws BeansException {
        // doGetBean才是真正向IOC容器获取被管理Bean的方法。
        return doGetBean(name, null, null, false);
    }
    // 根据给定的Bean名称和类型获取
    @Override
    public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
        return doGetBean(name, requiredType, null, false);
    }
    // 根据给定的Bean名称,类型和参数获取
    @Override
    public Object getBean(String name, Object... args) throws BeansException {
        return doGetBean(name, null, args, false);
    }

// 真正实现向IOC索取Bean的功能,触发依赖注入的入口。
    protected <T> T doGetBean(
            String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
            throws BeansException {
        // 根据指定名称获取被管理的Bean名称,剥离指定名称中对容器的相关依赖
        // 如果指定的是别名,将别名转换为规范的Bean名称。
        String beanName = transformedBeanName(name);
        Object beanInstance;
        // 先从缓存中读取是否已经有被创建过的单例Bean
        // 对于单例模式的Bean整个IOC容器只会创建一次。
        Object sharedInstance = getSingleton(beanName);
        // IOC容器创建单例模式的Bean对象
        if (sharedInstance != null && args == null) {
            if (logger.isTraceEnabled()) {
                // 如果在容器中已有指定名称和单例模式的Bean被创建,直接返回已经创建的Bean
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            // 获取给定的Bean实例对象,完成FactoryBean的相关处理
            // 注意:BeanFactory是管理Bean的工厂,FactoryBean是创建对象的工厂Bean,两者之间存在区别。
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // 缓存中没有正在创建的单例模式Bean,缓存中已存在原型模式Bean
            // 但是由于循环引用导致实例化对象失败
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // 对IOC容器中是否存在BeanDefinition进行检查,首先检查能否在当前BeanFactory中获取所需要的Bean。
            // 如果不能则委托当前容器的父容器进行查找,如果还是找不到则沿着容器继承体系继续向上查找。
            BeanFactory parentBeanFactory = getParentBeanFactory();
            // 当前容器的父容器存在,且当前容器中不存在指定名称的Bean
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // 解析Bean名称的原始名称
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory abf) {
                    return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // 委派父容器根据指定名称和显示的参数查找
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else if (requiredType != null) {
                    // 委派父容器根据指定名称和类型查找
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
                else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }
            // 创建的Bean是否需要进行类型验证(一般不需要)
            if (!typeCheckOnly) {
                // 向容器标记指定的Bean已经被创建
                markBeanAsCreated(beanName);
            }

            StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
                    .tag("beanName", name);
            try {
                if (requiredType != null) {
                    beanCreation.tag("beanType", requiredType::toString);
                }
                // 根据指定Bean名称获取其父级Bean定义
                // 主要解决Bean继承时子类和父类公共属性问题
                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // 获取当前Bean所有依赖Bean的名称
                String[] dependsOn = mbd.getDependsOn();
                // 如果Bean有依赖
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        // 把被依赖Bean注册给当前依赖的Bean
                        registerDependentBean(dep, beanName);
                        try {
                            // 递归调用getBean()方法,获取当前Bean的依赖Bean
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // 创建单例的Bean实例对象
                if (mbd.isSingleton()) {
                    // 使用匿名内部类创建Bean的实例对象,并注册所以来的对象
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            // 创建一个Bean实例对象,如果有父级继承,则合并子类和父类的定义
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // 显式地从容器中单例模式的Bean缓存中清楚实例对象
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    // 获取给定Bean的实例对象
                    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // 原型模式,如果Prototype则每次创建一个新的对象
                    Object prototypeInstance = null;
                    try {
                        // 回调beforePrototypeCreation()方法,默认的功能是注册当前创建的原型对象。
                        beforePrototypeCreation(beanName);
                        // 创建指定Bean的对象实例
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        // 回调afterPrototypeCreation()方法,默认功能是告诉IOC容器不再创建指定不过Bean的原型对象
                        afterPrototypeCreation(beanName);
                    }
                    // 获取Bean的实例对象
                    beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
                    // 要创建bean既不是单例模式也不是原型模式,则根据bean定义资源中配置的生命周期范围
                    // 选择实例化Bean的合适方法,这种方式在Web应用程序中较为常用request session application
                else {
                    String scopeName = mbd.getScope();
                    if (!StringUtils.hasLength(scopeName)) {
                        throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
                    }
                    Scope scope = this.scopes.get(scopeName);
                    // 如果Bean定义资源中没有配置生命周期范围,则Bean定义不合法
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        // 这里又使用了匿名内部类获取一个指定生命周期范围的实例
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        // 获取Bean的实例对象
                        beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new ScopeNotActiveException(beanName, scopeName, ex);
                    }
                }
            }
            catch (BeansException ex) {
                beanCreation.tag("exception", ex.getClass().toString());
                beanCreation.tag("message", String.valueOf(ex.getMessage()));
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
            finally {
                beanCreation.end();
            }
        }

        return adaptBeanInstance(name, beanInstance, requiredType);
    }

    @SuppressWarnings("unchecked")
    <T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType) {
        // 对创建的实例化对象进行类型检查
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return (T) convertedBean;
            }
            catch (TypeMismatchException ex) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }

}

如果Bean定义为单例模式则优先在缓存中进行查找,确保容器中只存在一个实例对象。如果定义为原型则每次都会创建按一个新的实例对象。而且Bean定义可以指定生命周期范围。doGetBean()只是定义类创建Bean实例的不同策列,具体Bean实例过程由实现了ObjectFactory接口使用委派模式,具体子类AbstractAutowireCapableBeanFactory完成。

下面再次分析下createBean()源码:

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

        // 封装被创建的Bean对象
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        // 获取实例化对象的接口
        Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // 调用PostProcessor后置处理器
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.markAsPostProcessed();
            }
        }

        // 向容器中缓存单例模式的Bean对象,以防止循环引
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isTraceEnabled()) {
                logger.trace("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            // 匿名内部类,为了防止循环引用,尽早持有对象的引用
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Bean对象的初始化,依赖注入由此触发
        // exposedObject对象在初始化完成之后返回依赖注入完成后的Bean
        Object exposedObject = bean;
        try {
            // 将bean实例对象封装,并将Bean定义中配置的属性值赋给实例对象
            populateBean(beanName, mbd, instanceWrapper);
            // 初始化Bean对象
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {
                throw bce;
            }
            else {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
            }
        }
        if (earlySingletonExposure) {
            // 获取指定名称的已注册的单例模式Bean对象
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                // 根据名称获取已注册的Bean和正在实例化的Bean是同一个
                if (exposedObject == bean) {
                    // 当前实例化bean初始化完成
                    exposedObject = earlySingletonReference;
                }
                // 当前Bean依赖其他Bean并且发生循环引用时不允许创建新的实例对象
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    // 获取当前Bean所依赖的所有Bean
                    for (String dependentBean : dependentBeans) {
                        // 对依赖Bean进行依赖类型检查
                        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 " +
                                "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        // Register bean as disposable.
        try {
            // 注册完成依赖注入的Bean
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

具体的依赖注入在createBeanInstance()生成Bean所包含的Java对象实例,populateBean()方法对Bean属性的依赖注入进行处理。

2.2,选择Bean实例化策略

在createBeanInstance()方法中,根据指定的初始化策略,使用简单工厂,工厂方法或者容器自动装配特性生成Java实例对象,创建对象源码如下:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // 确认Bean可实例化
        Class<?> beanClass = resolveBeanClass(mbd, beanName);
        // 使用工厂方法对Bean进行实例化
        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());
        }

        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {
            return obtainFromSupplier(instanceSupplier, beanName);
        }

        if (mbd.getFactoryMethodName() != null) {
            //调用工厂进行实例化
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // 使用容器的自动装配方法进行实例化
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            synchronized (mbd.constructorArgumentLock) {
                if (mbd.resolvedConstructorOrFactoryMethod != null) {
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        if (resolved) {
            if (autowireNecessary) {
                // 配置了自动装配属性,使用容器的自动装配进行实例化
                // 容器的自动装配根据参数类型装配Bean的构造方法
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                // 使用默认的无参构造方法进行实例化
                return instantiateBean(beanName, mbd);
            }
        }

        // 使用Bean构造方法进行实例化
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // 使用构造器自动装配特性,调用匹配的构造器方法进行实例化
        ctors = mbd.getPreferredConstructors();
        if (ctors != null) {
            return autowireConstructor(beanName, mbd, ctors, null);
        }
        // 使用默认的无参构造方法进行实例化
        return instantiateBean(beanName, mbd);
    }

对使用工厂方法和自动装配特性的Bean,调用相应的工厂方法或者参数匹配的构造方法即可完成实例化对象的工作,但是最长使用默认无参构造方法就需要使用相应的初始化策略JDK反射机制或者CGLib来进行初始化,在getInstantiationStrategy().instantiate()方法中实现了实例化。

2.3,准备依赖注入

依赖注入主要分为两个步骤,首先createBeanInstance()方法生成Bean所包含的Java对象实例,然后调用populateBean()方法对Bean属性的依赖注入进行处理:

       protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        if (bw == null) {
            if (mbd.hasPropertyValues()) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
            else {
                // Skip property population phase for null instance.
                return;
            }
        }

        if (bw.getWrappedClass().isRecord()) {
            if (mbd.hasPropertyValues()) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Cannot apply property values to a record");
            }
            else {
                // Skip property population phase for records since they are immutable.
                return;
            }
        }

        // 获取容器在解析Bean定义资源时为BeanDefinition设置的属性值
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
                if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    return;
                }
            }
        }

        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

        int resolvedAutowireMode = mbd.getResolvedAutowireMode();
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
            // Add property values based on autowire by name if applicable.
            if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }
            // Add property values based on autowire by type if applicable.
            if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }
            pvs = newPvs;
        }
        if (hasInstantiationAwareBeanPostProcessors()) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
                PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
                pvs = pvsToUse;
            }
        }

        boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
        if (needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }

        if (pvs != null) {
            // 对属性进行注入
            applyPropertyValues(beanName, mbd, bw, pvs);
        }
    }



 protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        if (pvs.isEmpty()) {
            return;
        }
        // 封装属性值
        MutablePropertyValues mpvs = null;
        List<PropertyValue> original;

        if (pvs instanceof MutablePropertyValues _mpvs) {
            mpvs = _mpvs;
            // 属性值已经转换
            if (mpvs.isConverted()) {
                // Shortcut: use the pre-converted values as-is.
                try {
                    // 为实例化对象设置属性值
                    bw.setPropertyValues(mpvs);
                    return;
                }
                catch (BeansException ex) {
                    throw new BeanCreationException(
                            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
                }
            }
            // 获取实例化对象原始类型值
            original = mpvs.getPropertyValueList();
        }
        else {
            original = Arrays.asList(pvs.getPropertyValues());
        }
        // 获取属性值对象的原始类型值
        TypeConverter converter = getCustomTypeConverter();
        if (converter == null) {
            converter = bw;
        }
        // 创建一个Bean定义属性值解析器,将Bean定义中属性值解析为Bean实例对象的实际值
        BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

        // 为属性的解析值创建一个副本,将副本数据注入实例对象
        List<PropertyValue> deepCopy = new ArrayList<>(original.size());
        boolean resolveNecessary = false;
        for (PropertyValue pv : original) {
            // 属性值无需转换
            if (pv.isConverted()) {
                deepCopy.add(pv);
            }
            else {
                // 需要转换

                String propertyName = pv.getName();
                // 原始的属性值,即转换之前的属性值。
                Object originalValue = pv.getValue();
                if (originalValue == AutowiredPropertyMarker.INSTANCE) {
                    Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
                    if (writeMethod == null) {
                        throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
                    }
                    originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
                }
                // 转换属性值,列入将引用转换为IOC容器中实例对象的引用
                Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
                // 转换后的属性值
                Object convertedValue = resolvedValue;
                // 属性值是否可以转换
                boolean convertible = bw.isWritableProperty(propertyName) &&
                        !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
                if (convertible) {
                    // 使用用户自定义类型转换器转换属性值
                    convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
                }
                // 存储转换后的属性值,避免每次属性注入时的转换工作
                if (resolvedValue == originalValue) {
                    if (convertible) {
                        // 设置属性转换之后的值
                        pv.setConvertedValue(convertedValue);
                    }
                    deepCopy.add(pv);
                }
                // 属性是可转换的且属性原始值是字符串类型,属性的原始类型值不是
                // 动态生成字符串,属性的原始值不是集合或者数组类型的
                else if (convertible && originalValue instanceof TypedStringValue typedStringValue &&
                        !typedStringValue.isDynamic() &&
                        !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
                    pv.setConvertedValue(convertedValue);
                    // 重新封装属性值
                    deepCopy.add(pv);
                }
                else {
                    resolveNecessary = true;
                    deepCopy.add(new PropertyValue(pv, convertedValue));
                }
            }
        }
        if (mpvs != null && !resolveNecessary) {
            // 标记属性值已经转换过
            mpvs.setConverted();
        }

        // 进行属性的依赖注入
        try {
            bw.setPropertyValues(new MutablePropertyValues(deepCopy));
        }
        catch (BeansException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
        }
    }

属性注入过程分为两种情况:

属性值类型不需要强制转换时,不需要解析属性值,直接进行依赖注入。

属性值类型需要进行强制转换时,首先要解析属性值,然后对解析后的属性值进行依赖注入,在其resolveValueIfNecessary()方法中进行的,对属性值的依赖注入是通过bw.setPropertyValues()方法

进行实现。

2.4,解析属性依赖注入规则

容器对属性进行依赖注入时,如果发现属性值需要进行类型转换,类如属性值是容器中另一个Bean实例对象的引用,则容器首先需要根据属性值解析出所引用的对象,然后才能将该引用对象注入到目标实例对象的属性上,对属性进行解析有resolveValueIfNecessary()方法实现,其源码如下:

// 解析属性值,对注入类型进行转换
    @Nullable
    public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
        // 对引用类型的属性进行解析
        if (value instanceof RuntimeBeanReference ref) {
            // 调用引用类型的属性进行解析
            return resolveReference(argName, ref);
        }
        // 对引用容器中另一个Bean名称的属性进行解析
        else if (value instanceof RuntimeBeanNameReference ref) {
            String refName = ref.getBeanName();
            refName = String.valueOf(doEvaluate(refName));
            // 从容器中获取指定名称的Bean
            if (!this.beanFactory.containsBean(refName)) {
                throw new BeanDefinitionStoreException(
                        "Invalid bean name '" + refName + "' in bean reference for " + argName);
            }
            return refName;
        }
        // 对Bean类型属性的解析,主要是指Bean中的内部类
        else if (value instanceof BeanDefinitionHolder bdHolder) {
            // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
            return resolveInnerBean(bdHolder.getBeanName(), bdHolder.getBeanDefinition(),
                    (name, mbd) -> resolveInnerBeanValue(argName, name, mbd));
        }
        else if (value instanceof BeanDefinition bd) {
            return resolveInnerBean(null, bd,
                    (name, mbd) -> resolveInnerBeanValue(argName, name, mbd));
        }
        else if (value instanceof DependencyDescriptor dependencyDescriptor) {
            Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
            Object result = this.beanFactory.resolveDependency(
                    dependencyDescriptor, this.beanName, autowiredBeanNames, this.typeConverter);
            for (String autowiredBeanName : autowiredBeanNames) {
                if (this.beanFactory.containsBean(autowiredBeanName)) {
                    this.beanFactory.registerDependentBean(autowiredBeanName, this.beanName);
                }
            }
            return result;
        }
        // 对集合数组类型的属性进行解析
        else if (value instanceof ManagedArray managedArray) {
            // 获取数组的类型
            Class<?> elementType = managedArray.resolvedElementType;
            if (elementType == null) {
                // 获取数组元素的类型
                String elementTypeName = managedArray.getElementTypeName();
                if (StringUtils.hasText(elementTypeName)) {
                    try {
                        //  使用反射机制创建指定类型的对象
                        elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
                        managedArray.resolvedElementType = elementType;
                    }
                    catch (Throwable ex) {
                        // Improve the message by showing the context.
                        throw new BeanCreationException(
                                this.beanDefinition.getResourceDescription(), this.beanName,
                                "Error resolving array type for " + argName, ex);
                    }
                }
                // 没有获取到数组的类型,也没有获取到数组元素的类型
                else {
                    elementType = Object.class;
                }
            }
            // 创建指定类型的数组
            return resolveManagedArray(argName, (List<?>) value, elementType);
        }
        // 解析list类型的属性值
        else if (value instanceof ManagedList<?> managedList) {
            // May need to resolve contained runtime references.
            return resolveManagedList(argName, managedList);
        }
        // 解析set类型的属性值
        else if (value instanceof ManagedSet<?> managedSet) {
            // May need to resolve contained runtime references.
            return resolveManagedSet(argName, managedSet);
        }
        // 解析map类型属性值
        else if (value instanceof ManagedMap<?, ?> managedMap) {
            // May need to resolve contained runtime references.
            return resolveManagedMap(argName, managedMap);
        }
        // 解析props类型的属性值,porps其实就是key和value均为字符串的map
        else if (value instanceof ManagedProperties original) {
            Properties copy = new Properties();
            // 创建一个副本,作为解析后的返回值
            original.forEach((propKey, propValue) -> {
                if (propKey instanceof TypedStringValue typedStringValue) {
                    propKey = evaluate(typedStringValue);
                }
                if (propValue instanceof TypedStringValue typedStringValue) {
                    propValue = evaluate(typedStringValue);
                }
                if (propKey == null || propValue == null) {
                    throw new BeanCreationException(
                            this.beanDefinition.getResourceDescription(), this.beanName,
                            "Error converting Properties key/value pair for " + argName + ": resolved to null");
                }
                copy.put(propKey, propValue);
            });
            return copy;
        }
        // 解析字符串类型的属性值
        else if (value instanceof TypedStringValue typedStringValue) {
            // Convert value to target type here.
            Object valueObject = evaluate(typedStringValue);
            try {
                // 获取属性的目标类型
                Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
                if (resolvedTargetType != null) {
                    // 对目标类型的属性进行解析,递归调用
                    return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
                }
                // 没有获取到属性的目标对象,则按Object类型返回
                else {
                    return valueObject;
                }
            }
            catch (Throwable ex) {
                // Improve the message by showing the context.
                throw new BeanCreationException(
                        this.beanDefinition.getResourceDescription(), this.beanName,
                        "Error converting typed String value for " + argName, ex);
            }
        }
        else if (value instanceof NullBean) {
            return null;
        }
        else {
            return evaluate(value);
        }
    }

// 解析引用类型的属性值
    @Nullable
    private Object resolveReference(Object argName, RuntimeBeanReference ref) {
        try {
            Object bean;
            // 获取引用的Bean名称
            Class<?> beanType = ref.getBeanType();
            // 如果引用的对象在父类容器中则从父类容器中获取指定的引用对象
            if (ref.isToParent()) {
                BeanFactory parent = this.beanFactory.getParentBeanFactory();
                if (parent == null) {
                    throw new BeanCreationException(
                            this.beanDefinition.getResourceDescription(), this.beanName,
                            "Cannot resolve reference to bean " + ref +
                                    " in parent factory: no parent factory available");
                }
                if (beanType != null) {
                    bean = parent.getBean(beanType);
                }
                else {
                    bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName())));
                }
            }
            else {
                String resolvedName;
                if (beanType != null) {
                    NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
                    bean = namedBean.getBeanInstance();
                    resolvedName = namedBean.getBeanName();
                }
                // 从当前的容器中获取指定的引用Bean对象,如果指定Bean没有被实力化
                // 则会递归触发引用Bean的初始化和依赖注入
                else {
                    resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
                    bean = this.beanFactory.getBean(resolvedName);
                }
                // 当前实例化对象依赖的引用对象
                this.beanFactory.registerDependentBean(resolvedName, this.beanName);
            }
            if (bean instanceof NullBean) {
                bean = null;
            }
            return bean;
        }
        catch (BeansException ex) {
            throw new BeanCreationException(
                    this.beanDefinition.getResourceDescription(), this.beanName,
                    "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
        }
    }

// 解析array类型的属性值
    private Object resolveManagedArray(Object argName, List<?> ml, Class<?> elementType) {
        // 创建一个指定类型的数组,用于存放和返回解析后的数组
        Object resolved = Array.newInstance(elementType, ml.size());
        for (int i = 0; i < ml.size(); i++) {
            // 递归解析array的每一个元素,并将解析后的值设置到resolved数组中,索引为i
            Array.set(resolved, i, resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
        }
        return resolved;
    }

上面的源码发现Spring是如何对引用类型,内部类及集合类型的属性进行解析的,解析完成后就可以进行依赖注入了,依赖注入过程就是将Bean对象设置到他所以来的Bean对象属性上,真正的依赖注入是通过bw.setPropertyValues()方法实现的,该方法也使用了委派模式,在BeanWrapper接口中至少定义了方法声明,依赖注入部分有BeanWrapperImpl完成。

2.5,注入赋值

BeanWrapplerImpl类符合对容器中完成初始化的Bean实例对象进行属性的依赖注入,即把Bean对象设置到它所依赖的另一个Bean属性上。

    protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
        if (tokens.keys != null) {
            processKeyedProperty(tokens, pv);
        }
        else {
            processLocalProperty(tokens, pv);
        }
    }

private void processKeyedProperty(PropertyTokenHolder tokens, PropertyValue pv) {
        // 调用属性的getter(readerMetrhod)方法获取属性值
        Object propValue = getPropertyHoldingValue(tokens);
        PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
        if (ph == null) {
            throw new InvalidPropertyException(
                    getRootClass(), this.nestedPath + tokens.actualName, "No property handler found");
        }
        Assert.state(tokens.keys != null, "No token keys");
        String lastKey = tokens.keys[tokens.keys.length - 1];
        // 注入array类型的属性值
        if (propValue.getClass().isArray()) {
            Class<?> requiredType = propValue.getClass().getComponentType();
            int arrayIndex = Integer.parseInt(lastKey);
            Object oldValue = null;
            try {
                if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
                    oldValue = Array.get(propValue, arrayIndex);
                }
                Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
                        requiredType, ph.nested(tokens.keys.length));
                // 获取集合类型属性的长度
                int length = Array.getLength(propValue);
                if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
                    Class<?> componentType = propValue.getClass().getComponentType();
                    Object newArray = Array.newInstance(componentType, arrayIndex + 1);
                    System.arraycopy(propValue, 0, newArray, 0, length);
                    int lastKeyIndex = tokens.canonicalName.lastIndexOf('[');
                    String propName = tokens.canonicalName.substring(0, lastKeyIndex);
                    setPropertyValue(propName, newArray);
                    // 调用属性的getter获取属性值
                    propValue = getPropertyValue(propName);
                }
                // 将属性值赋给数组中的元素
                Array.set(propValue, arrayIndex, convertedValue);
            }
            catch (IndexOutOfBoundsException ex) {
                throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
                        "Invalid array index in property path '" + tokens.canonicalName + "'", ex);
            }
        }
        // 注入list类型的属性值
        else if (propValue instanceof List list) {
            // 获取list集合类型
            Class<?> requiredType = ph.getCollectionType(tokens.keys.length);
            int index = Integer.parseInt(lastKey);
            Object oldValue = null;
            // 如果list的长度大于属性值的长度,则将多余的元素赋值为null
            if (isExtractOldValueForEditor() && index < list.size()) {
                oldValue = list.get(index);
            }
            Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
                    requiredType, ph.nested(tokens.keys.length));
            int size = list.size();
            if (index >= size && index < this.autoGrowCollectionLimit) {
                for (int i = size; i < index; i++) {
                    try {
                        list.add(null);
                    }
                    catch (NullPointerException ex) {
                        throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
                                "Cannot set element with index " + index + " in List of size " +
                                size + ", accessed using property path '" + tokens.canonicalName +
                                "': List does not support filling up gaps with null elements");
                    }
                }
                list.add(convertedValue);
            }
            else {
                // 将值添加到list中
                try {
                    list.set(index, convertedValue);
                }
                catch (IndexOutOfBoundsException ex) {
                    throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
                            "Invalid list index in property path '" + tokens.canonicalName + "'", ex);
                }
            }
        }
        // 注入map类型的属性值
        else if (propValue instanceof Map map) {
            // 获取map集合key的类型
            Class<?> mapKeyType = ph.getMapKeyType(tokens.keys.length);
            // 获取map集合value的类型
            Class<?> mapValueType = ph.getMapValueType(tokens.keys.length);
            TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType);
            // 解析map类型的属性key值
            Object convertedMapKey = convertIfNecessary(null, null, lastKey, mapKeyType, typeDescriptor);
            Object oldValue = null;
            if (isExtractOldValueForEditor()) {
                oldValue = map.get(convertedMapKey);
            }
            // 解析map类型的属性value值
            Object convertedMapValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
                    mapValueType, ph.nested(tokens.keys.length));
            // 将解析后的key和value值赋给map属性
            map.put(convertedMapKey, convertedMapValue);
        }

        else {
            throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
                    "Property referenced in indexed property path '" + tokens.canonicalName +
                    "' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
        }
    }

    private Object getPropertyHoldingValue(PropertyTokenHolder tokens) {
        // Apply indexes and map keys: fetch value for all keys but the last one.
        Assert.state(tokens.keys != null, "No token keys");
        PropertyTokenHolder getterTokens = new PropertyTokenHolder(tokens.actualName);
        getterTokens.canonicalName = tokens.canonicalName;
        getterTokens.keys = new String[tokens.keys.length - 1];
        System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);

        Object propValue;
        try {
            // 获取属性值
            propValue = getPropertyValue(getterTokens);
        }
        catch (NotReadablePropertyException ex) {
            throw new NotWritablePropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
                    "Cannot access indexed value in property referenced " +
                    "in indexed property path '" + tokens.canonicalName + "'", ex);
        }

        if (propValue == null) {
            // null map value case
            if (isAutoGrowNestedPaths()) {
                int lastKeyIndex = tokens.canonicalName.lastIndexOf('[');
                getterTokens.canonicalName = tokens.canonicalName.substring(0, lastKeyIndex);
                propValue = setDefaultValue(getterTokens);
            }
            else {
                throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + tokens.canonicalName,
                        "Cannot access indexed value in property referenced " +
                        "in indexed property path '" + tokens.canonicalName + "': returned null");
            }
        }
        return propValue;
    }

对于集合类型的属性,将属性解析为目标类型的集合后直接赋值给属性

对于非集合类型的属性,大量使用JDK反射机制,通过属性的getter()方法获取指定属性注入前的值,同时调用属性setter()方法为属性设置注入后的值。

  1. IOC容器中那些鲜为人知的细节

Spring ioc容器存在一些高级特性,如使用lazy-init属性对Bean预初始化,使用FactoryBean产生或者修饰Bean对象的生成,IOC容器在初始化Bean过程中使用BeanPostProcessor后置处理器对Bean声明周期时间进行管理等。

3.1,关于延迟加载

IOC容器初始化过程就是对Bean定义资源的定位,载入,注册。此时容器的依赖注入并没有发生,依赖注入是在应用程序第一次向容器索取Bean时通过getBean()方法完成。

当Bean定义资源的<bean>元素配置了lazy-init=false属性时,容器将会在初始化时对所配置的Bean进行预实例化,Bean的依赖注入在容器初始化时就已经完成。这样当容器应用第一次向容器获取时就无需初始化和对bean依赖注入了。而是直接从容器获取。

3.1.1 refresh():IOC容器读入已经定位的Bean定义资源是从refresh()方法开始的,我们AbstractApplicationContext类的refresh()方法入手分析,在refresh()方法中ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()启动了bean定义资源的载入,注册过程。finishBeanFactoryInitialization()方法是对注册后的Bean定义中的预实例化lazy-init=false spring默认进行实例化即为true的bean进行处理的地方。

3.1.2 fuinishBeanFactorInitiaIization()处理预实例化的Bean:bean定义资源被载入IOC容器后,容器将Bean的定义资源解析为内部的数据结构BeanDefinition并注册到容器中。AbstractApplicationContext类中fuinishBeanFactorInitiaIization()方法对配置了预实例化属性bean进行预初始化。

3.1.3 对配置了Lazy-init属性的单例模式Bean预实例化;

若设置了lazy-init属性,则容器在完成bean定义的注册之后,会通过getBean()方式触发指定Bean的初始化和依赖注入。

3.1.4 关于FactoryBean和BeanFactory

BeanFactory:Bean工厂,ioc容器顶级接口,主要管理Bean。实例化,定位,配置应用程序中对象及建立这些对象之间的依赖。

FactoryBean:工厂Bean,是一个Bean,作用是产生其他Bean实例。这种Bean没什么特别要求,仅提供一个工厂方法返回其他bean实例。多数情况无序这样做因为容器担任工厂的角色,少数情况下容器中的Bean本身就是工厂其作用产生其他bean实例。

  1. autowiring

IOC容器提供了两种管理Bean依赖关系的方式:

1,显示管理:通过BeanDefinition的属性值和构造方法实现Bean依赖关系管理。

2,autowiring:Spring IOC容器有依赖自动装配功能,不需要对Bean的依赖关系显式声明,只需配置好autowiring属性。IOC容器会自动使用反射查找属性的类型和名称,基于属性类型或者名称自动匹配容器中的bean,从而完成依赖注入。

1,AbstractAutoWireCapabIeBeanFactory对Bean实例对象进行属性依赖注入。

应用程序第一次通过getBean()方法向容器索取Bean时,容器创建Bean实例对象,并且对Bean实例对象进行属性依赖注入,AbstractAutoWire-CapableBeanFactory的populateBean()实现了属性依赖注入功能:

2,SpringIOC容器根据Bean名称或者类型进行autowiring自动属性依赖注入。

容器根据Bean名称或者类型进行autowiring自动属性依赖注入的重要代码如下:

通过源码来看,通过属性名自动注入比属性类型自动注入要简单,但时真正实现睡醒注入的时DefaultSingletonBeanRegistry类的registerDependentBean()方法。

3.DefauItSingIetonBeanRegistry的registerDependentBean()方法

实现属性依赖注入。

可以看出Autowiring实现过程如下:

对Bean的属性调用getBean()方法,完成依赖Bean的初始化和依赖注入。

将依赖Bean属性引用设置到被依赖的Bean属性上。

将依赖Bean的名称和被依赖Bean的名称存储在IOC容器的集合中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值