Spring-IoC-依赖注入

9次阅读

共计 15964 个字符,预计需要花费 40 分钟才能阅读完成。

前言

上一篇文章中,我们介绍了 Spring IoC 的容器初始化过程 – IoC 容器初始化

本篇文章中,我们继续介绍 Spring IoC 依赖注入的过程和源码解读。

还是如之前一样,为大家梳理一下步骤流程,以便于大家能在心里有个大概的脉络,更容易读懂源码,更容易抓住重点。

主要内容:

  • beanName 解析转换
  • 手动注册 Bean 检测
  • 双亲容器检测
  • 依赖初始化(递归)
  • ★ 创建 singleton 实例

    • 对象实例化
    • 属性装配
    • 处理 Bean 创建之后的各种回调事件

源码解析

上一章最后一节,容器初始化的倒数第二步,finishBeanFactoryInitialization(beanFactory)实例化所有单例,调用了 getBean() 方法来做 singleton bean 的实例化操作。这就是 Spring IoC 依赖注入的入口。

在开始之前,有一点需要提一下。前面我们是从容器初始化之后进来的,但实际操作中,我们有可能是在程序普通运行情况下,用 ApplicationContext.getBean() 去获取容器中 bean。不要局限于刚刚的视角中。

现在让我们开始吧。

首先看看getBean()

源码位置:AbstractBeanFactory#getBean(String name)

    @Override
    public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);
    }

doGetBean()

deGetBean()

  • beanName 解析转换
  • 检测 手动注册 Bean
  • 双亲容器检测
  • 依赖初始化(递归)
  • 创建 Bean createBean()
    protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {
        // 反正就是获取到真正 beanName
        // 处理两个情况,1. 将别名转化成真的 beanName;2. 把 FactoryBean 的前缀 "&" 给去了
        final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        // 检测已经注册的 Bean,保证不重复创建
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {if (logger.isDebugEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean'" + beanName +
                            "'that is not fully initialized yet - a consequence of a circular reference");
                }
                else {logger.debug("Returning cached instance of singleton bean'" + beanName + "'");
                }
            }
            // 这个方法还是有点逻辑的
            // 如果目前获得的 sharedInstance 不是 FactoryBean,那 bean 就赋值成 sharedInstance,直接返回
            // 如果是 FactoryBean 就返回 FactoryBean 创建的实例,// 这个也是 FactoryBean 的知识点,我在我的另一篇文章也讲过了,bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // Fail if we're already creating this bean instance:
            // 直接翻译:创建过了此 beanName 的 prototype 类型的 bean,那么抛异常
            // We're assumably within a circular reference.
            // 往往是因为陷入了循环引用
            if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            // 检查下这个 BeanDefinition 是否存在
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                // 当前容器没有这个 BeanDefinition,去 parent 容器去找
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            if (!typeCheckOnly) {markBeanAsCreated(beanName);
            }

            try {
                // 这个 getMergedLocalBeanDefinition 前面讲过哦
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // 先初始化依赖的所有 Bean,这个很好理解。// 注意,这里的依赖指的是 depends-on 中定义的依赖
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {
                            // 这里循环依赖概念不要紊乱了
                            // 这里指的是通过 depends-on 定义造成的循环依赖,// 我们另外一种类成员式的循环引用 Spring 是支持的
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between'" + beanName + "'and'" + dep + "'");
                        }
                        // 注册依赖关系
                        // 这么做的原因是 Spring 在即将进行 bean 销毁的时候会【首先销毁被依赖的 bean】。// 看 SpringBean 的初始化和销毁顺序就知道了, 依赖关系的保存目的就是这个
                        // 依赖关系的保存是通过一个 ConcurrentHashMap<String, Set> 完成的,key 是 bean 的真实名字。registerDependentBean(dep, beanName);
                        try {
                            // 先去初始化被依赖项
                            // 递归然后反递归回来
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'"+ beanName +"' depends on missing bean '"+ dep +"'", ex);
                        }
                    }
                }

                // Create bean instance.
                // 如果是 singleton scope 的,创建 singleton 的实例
                if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                // 创建 Bean 的详情,等下拉出来单独说
                                return createBean(beanName, mbd, args);
                            }
                            catch (BeansException ex) {
                                // Explicitly remove instance from singleton cache: It might have been put there
                                // eagerly by the creation process, to allow for circular reference resolution.
                                // Also remove any beans that received a temporary reference to the bean.
                                destroySingleton(beanName);
                                throw ex;
                            }
                        }
                    });
                    // 前面讲过了
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                // 如果是 prototype scope 的,创建 prototype 的实例
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                // 如果不是 singleton 和 prototype 的话,需要委托给相应的实现类来处理
                // 这里非重点,我们的重点是 singleton 的创建
                else {String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {throw new IllegalStateException("No Scope registered for scope name'" + scopeName + "'");
                    }
                    try {Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {beforePrototypeCreation(beanName);
                                try {return createBean(beanName, mbd, args);
                                }
                                finally {afterPrototypeCreation(beanName);
                                }
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope'" + scopeName + "'is not active for the current thread; consider" +
                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
            }
            catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        // Check if required type matches the type of the actual bean instance.
        // 最后再检查下类型对不对,不对就抛异常了,对的话就返回
        if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
            try {return getTypeConverter().convertIfNecessary(bean, requiredType);
            }
            catch (TypeMismatchException ex) {if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean'" + name + "'to required type'" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }

doCreateBean()

步骤概览:

  1. 开始是单例的话要先清除缓存;
  2. 实例化 bean,将 BeanDefinition 转换为 BeanWrapper;
  3. 使用 MergedBeanDefinitionPostProcessor,Autowired 注解就是通过此方法实现类型的预解析;
  4. 解决循环依赖问题;
  5. 填充属性,将属性填充到 bean 实例中;
  6. 注册 DisposableBean;
  7. 创建完成并返回

三个关注点:

  1. createBeanInstance() 实例化
  2. populateBean(); 属性装配
  3. initializeBean() 处理 Bean 初始化之后的各种回调事件
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        // 这个 BeanWrapper 是创建出来持有对象的
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            // 如果是 singleton,先把缓存中的同名 bean 消除
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) 
            // 关键代码,后面拉出来单独讲
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
        mbd.resolvedTargetType = beanType;

        // Allow post-processors to modify the merged bean definition.
        // 涉及接口:MergedBeanDefinitionPostProcessor
        // 不是关键逻辑,不讲了
        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.postProcessed = true;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        // 这里是为了解决循环依赖的,先把初步实例化的 Bean 实例的引用缓存起来,暴露出去,// 这个可以结合别的文章学习,面试题常考,我后面可能也会写
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean'" + beanName +
                        "'to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            // 时序图中的一步,关键步骤,属性装配,前面的实例只是实例化,没有装配属性
            // 和前面的 createBeanInstance 一样会拉出来讲,继续看下去吧
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                // 还记得 init-method 吗?还有 InitializingBean 接口?还有 BeanPostProcessor 接口?// 这里就是处理 bean 初始化完成后的各种回调
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }
        catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }


        // 这个逻辑分支我一次性说完吧。// 如果该 beanName 对象已经注册单例模式,则从单例中获取,并判断获取到的 bean 实例 (B) 与 BeanWrapper 中的 bean 实例 (A) 是同一个实例,如果是,则返回 A 或者 B,如果不是,则递归找出它的依赖 bean。if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);
             // earlySingletonReference 只有在检测到有循环依赖的情况下才会不为空
            if (earlySingletonReference != null) {if (exposedObject == bean) {
                    // 两个是同一个引用,bean 初始化完成
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<String>(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.");
                    }
                }
            }
        }

        // Register bean as disposable.
        // 注册 DisposableBean;try {registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

上一步的三个关注点,分开来讲。

1. createBeanInstance()

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
        // Make sure bean class is actually resolved at this point.
        // 解析出 Class
        Class<?> beanClass = resolveBeanClass(mbd, beanName);

        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        }

        // 如果工厂方法不为空,则是用工厂方法初始化
        if (mbd.getFactoryMethodName() != null)  {
            // 相关知识点看另一篇文章关于 FactoryBean 的
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // Shortcut when re-creating the same bean...
        // 如果不是第一次创建,比如第二次创建 prototype bean。// 这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入 来完成实例化
        // 所以注释说叫 shortcut
        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) {
                // 构造方法自动注入
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                // 默认构造方法
                return instantiateBean(beanName, mbd);
            }
        }

        // Need to determine the constructor...
        // 判断是否采用有参构造函数
        // 构造器自动装配
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {return autowireConstructor(beanName, mbd, ctors, args);
        }

        // No special handling: simply use no-arg constructor.
        // 使用无参构造器
        return instantiateBean(beanName, mbd);
    }

2. populateBean(); 属性装配

入口方法: AbstractAutowireCapableBeanFactory#populateBean

它的作用是: 根据 autowire 类型进行 autowire by nameby type 或者是直接进行设置

    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {PropertyValues pvs = mbd.getPropertyValues();

        if (bw == null) {if (!pvs.isEmpty()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
            else {
                // Skip property population phase for null instance.
                return;
            }
        }

        // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
        // state of the bean before properties are set. This can be used, for example,
        // to support styles of field injection.
        // 这里看注解是一个扩展点 
        // InstantiationAwareBeanPostProcessor 的实现类可以在这里对 bean 进行状态修改
        // 不是个常用的扩展点,这里不讲了
        boolean continueWithPropertyPopulation = true;

        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    // 如果返回 false,代表不需要进行后续的属性设值,也不需要再经过其他的 BeanPostProcessor 的处理
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (!continueWithPropertyPopulation) {return;}

        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

            // Add property values based on autowire by name if applicable.
            // 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);
            }

            // Add property values based on autowire by type if applicable.
            // 通过类型装配
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

        if (hasInstAwareBpps || needsDepCheck) {PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        // InstantiationAwareBeanPostProcessor.postProcessPropertyValues 方法
                        // 代表能对属性值进行修改的能力
                        // 其中一个很有用实现类提一下,AutowiredAnnotationBeanPostProcessor
                        // 对采用 @Autowired 和 @Value 设值的就是这个 BeanPostProcessor 干的。// 不展开讲了,不然要讲不完了
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {return;}
                    }
                }
            }
            if (needsDepCheck) {checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }
        // 这里才是设置 bean 实例的属性值
        applyPropertyValues(beanName, mbd, bw, pvs);
    }

3. initializeBean() 处理 Bean 初始化之后的各种回调事件

看这个方法的 javadoc 描述

Initialize the given bean instance, applying factory callbacks as well as init methods and bean post processors.

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            // 涉及到的回调接口点进去一目了然,代码都是自解释的
            // BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // BeanPostProcessor 的 postProcessBeforeInitialization 回调
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // init-methods
            // 或者是实现了 InitializingBean 接口,会调用 afterPropertiesSet() 方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            // BeanPostProcessor 的 postProcessAfterInitialization 回调
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }

大家发现没有,BeanPostProcessor 的两个回调都发生在这边,只不过中间处理了 init-method。这和我原来的认知有点不一样了?因为 Spring 的源码中代码的命名很多时候是自解释的,很多时候我看英文就知道这些方法的意图,但在这里,为什么 BeanPostProcessor 的前置处理方法 postProcessBeforeInitialization() 也是在属性设置完成后调用的?

后面查询了去看英文的解释,

BeanPostProcessor is used to interact with newly created bean instances before and/or after their initialization method is invoked by the Spring container. You can use BeanPostProcessor to execute custom logic before and/or after bean’s initialization method is invoked by the Spring container.

BeanPostProcessor 的意图就是在初始化方法的前后做定制化操作。仔细想想好像这个命名也没毛病。如果真的是在 SpringBean 实例化之前调用应该叫 BeforeInstantiation。源码中的initialization 指的就是上面的 invokeInitMethods 操作。

结语

以上,就是关于 Spring IoC 依赖注入的主要内容。

Spring IoC 容器这里还有一些其他的知识点,有关于 SpringIoC 特性的。比如,Spring bean 的生命周期、FactoryBean、BeanPostProcessor,都是在使用 Spring IoC 容器经常遇到的特性。在了解了 IoC 容器的整体运行原理以后,你应该能够对这些特性进行一些分析,将你使用这些特性的方法和源码结合起来,融会贯通。

至此,Spring IoC 关于依赖注入的源码“大致”解读完毕,还是那句话,上面的源码解析,肯定不会是完备的,只是提取了我认为重要的东西。

如有疏漏,敬请谅解和自己查阅相关资料学习。如果错误,敬请指正!

本文由博客一文多发平台 OpenWrite 发布!

正文完
 0