Spring IoC - 依赖注入

undefined

前言

上一篇文章中,我们介绍了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 发布!

猜你喜欢

转载自juejin.im/post/5da7a0555188257a7306822d