3.DI运行时序

DI运行时序

概念

依赖注入,就是Spring从 Ioc容器里面,取出需要的bean(一个实例) ,然后注入/装配到 需要的地方。

BeanFactory

BeanFactory 则定义了最基本的功能,向其他功能提供 getBean( arge....)的功能定义,这是Spring中,IOC概念的重要接口,它的子类根据自己的需求多样化实现了getBean。

/**
 * BeanFactory作为最顶层的一个接口类,它定义了IOC容器的基本功能规范,BeanFactory 有三个子类
 */
public interface BeanFactory {

    // BeanFactory 提供了多个 getBean 接口定义,所有的beanFactory都必须要实现这些接口
    Object getBean(String name) throws BeansException;
    
    ......
    
    }

AbstractBeanFactory (简称 AbBD)

AbBD 是一个抽象类,也是对BeanFactory 进行实现的基类

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory{
    //对BeanFactory#getBean()的实现
    getBean(....){
        doGetBean( ...);
    }

    // 这是getBean 的核心实现,也是IOC 获得Bean的核心方法
   doGetBean(   ){
   
   ......
   }
}

实现层级

[图片上传失败...(image-97a893-1592449507292)]

  • 从父类接口来看,AbBD 继承了 父接口 HierarchicalBeanFactory ,这表示,AbBD 拥有父层级BeanFactory功能(这个功能允许 doGetBean()方法中, 在查找 beanDefinition时,先委派给 父类 BeanFactory 进行 beanDefinition 查找 ,类似于 双亲委派模式)
  • AbBD 继承了 抽象类FactoryBeanRegistrySupport,拥有了 通过 预先定义的单例FactoryBean 获取 单例 instance 的能力
  • [图片上传失败...(image-caefb6-1592449507298)]

核心方法 AbBD#doGetBean

  • 先从总体上浏览一下,doGetBean的业务流程 分为三个部:
if (是否存在于单例池中){
    。。。。。
       }else{
       
        如果没有,则进行常态创建
    }
if (进行类型检查){
    。。。。。
        }
return (T)bean;

接下来,看看具体代码实现:

    @SuppressWarnings("unchecked")
    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
        // 根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
        //如果指定的是别名,将别名转换为规范的Bean名称
        final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        /**
         * 即时检查单例缓存,是否手动注册过的单例
         * 这个方法内部会对未创建的单例bean进行一系列的创建、缓存并返回
         */
        Object sharedInstance = getSingleton(beanName);
        ...
  • AbBD#getSingleton(beanName)的实现如下:
    @Override
    @Nullable
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }

    /**
     * Return the (raw) singleton object registered under the given name.
     * <p>Checks already instantiated singletons and also allows for an early
     * reference to a currently created singleton (resolving a circular reference).
     * @param beanName the name of the bean to look for
     * @param allowEarlyReference whether early references should be created or not
     * @return the registered singleton object, or {@code null} if none found
     *
     *
     * 锁住该单例map,从预备单例池中取出该单例,进行单例创建
     这个单例池,有很多的 单例会提前加入进来,比如,在 AbstractApplication#refresh#prepareBeanFactory的时候,会有很多容器相关的单例对象加入到这个map池中,比如,“environment”,“systemProperties”等。
     
     */
    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        //从单例池map中,获得单例,如果单例池中没有该单例 且 单例创建set中油存在该单例
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            //进入if 锁住该单例map,从预备单例池中取出该单例,进行单例创建
            synchronized (this.singletonObjects) {
                //从 单例预备池中,取出单例
                singletonObject = this.earlySingletonObjects.get(beanName);
                //如果不在预备池中 且 该bean允许进行 early references 即时连接
                if (singletonObject == null && allowEarlyReference) {
                    //进入if 根据 beanName 获得单例工厂
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    //单例工厂不为null 进行
                    if (singletonFactory != null) {
                        //singletonFactory.getObject 委托给子类去实现 获得单例
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

这是一个向单例池中放入单例的场景,而且是IOC容器初始化的时候放进去的,可以认为是Spring自己放入的,对于应用十分基础且必要的单例对象。
[图片上传失败...(image-5243d6-1592449507298)]

然后,我们再跳回到 doGetBean方法里,继续看下去,如果能够获取到单例,则进入if分支:

        
        ……
        Object sharedInstance = getSingleton(beanName);
        
        if (sharedInstance != null && args == null) {
            if (logger.isTraceEnabled()) {
                /**
                 * 如果 name在 Set<String> singletonsCurrentlyInCreation 创建中的列表,这个逻辑很好理解
                 * 会提示,还没有该单例处于创建中
                 */
                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的单例实例,如果sharedInstance是FactoryBean,则通过FactoryBean的获得最终的目标bean,如果不是FactoryBean,则直接返回该sharedInstance

             * 注意:BeanFactory是管理容器中Bean的工厂,而FactoryBean是创建创建对象的工厂Bean,两者之间有区别
             */
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
  • bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 这行代码的具体实现如下:
        protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

        // Don't let calling code try to dereference the factory if the bean isn't a factory.
        // 检查name 是否由&开头,却又不是 FactoryBean,&这个符号不用多说,是由BeanFactory老祖宗定下的
        if (BeanFactoryUtils.isFactoryDereference(name)) {

            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            if (!(beanInstance instanceof FactoryBean)) {
                // 由 & 开始,但又不是 FactoryBean 就报错
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
        }

        /**
         * 对 beaninstance 进行最终处理,如果是 普通的bean ,就直接返回
         * 如果是 Factorybean 就
         *      1.先从 factoryBeanObjectCache 中获取缓存
         *      2.如果没有缓存,再通过工厂去获得 instance
         */
        // Now we have the bean instance, which may be a normal bean or a FactoryBean.
        // If it's a FactoryBean, we use it to create a bean instance, unless the
        // caller actually wants a reference to the factory.
        if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
            return beanInstance;
        }

        Object object = null;
        if (mbd == null) {
            // 从缓存中获取 instance,这个是由 FactoryBeanRegistrySupport 提供的
            object = getCachedObjectForFactoryBean(beanName);
        }
        if (object == null) {
            // Return bean instance from factory.
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            // Caches object obtained from FactoryBean if it is a singleton.
            if (mbd == null && containsBeanDefinition(beanName)) {
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }
  • 到了这里,可以看到 sharedInstance != null && args == null 判断就走完了,如果没有单例缓存池里找到,则进入到else 语句
        
        
        /**
         * 如果  sharedInstance在单例 中找不到    
        * todo 到了这个else,可以表示 这个instance 非单例吗?
         */
        else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            /**
             * 检查 是否创建中
             * 如果这个 beanname 位于 正在创建池中,这个池子由ThreadLocal实现,则抛出异常
             * 根据其他资料看,有说法 : 如果当前的bean已经被创建,获取会失败,表示可能有别的bean在引用该bean
             */
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            //父beanFactory存在,且 benaDefinition没有在父beanFactory中
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                /**
                // 如果该beanFactory 具有父beanFactory层级,则委托给父类先进行查询,类似于双亲委派模式
                // AbstractBeanFactory impl ConfigurableBeanFactory impl HierarchicalBeanFactory
                 HierarchicalBeanFactory 定义了beanFactory 是具有父BeanFactory层级的。
                */
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    //遍历祖先,进行查询
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    //如果参数 不为 null,则委托给父工厂
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else if (requiredType != null) {
                    //bean的真实类型
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
                else {
                    //这里表示args和requiredType都为null,直接通过得到的bean的名字去获取实例
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }

            if (!typeCheckOnly) {
        /** 
        * 如果不检查类型,则 mergedBeanDefinitions中移除该beanname, 
        * 同时加入到 this.alreadyCreated.add(beanName); 已创建的缓存池中 
        */
            markBeanAsCreated(beanName);
            }

            try {
                /**
                 * 从本地拿到 BD  合并父子bean的定义
                 */
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                //检查是否抽象类 -》 抽象类不能被实例化,会抛出错误
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                
                // ************** 先 遍历 bean的依赖项、*******************
                
                String[] dependsOn = mbd.getDependsOn();
                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 {
                            //根据依赖beanname,创建 依赖的bean实例
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }
                // ************** bean的依赖项遍历创建完成*******************

                // Create bean instance.
                // 创建 bean 实例
                if (mbd.isSingleton()) {
                    //从单例池中获取,或者创建一个单例,并注册到单例池map, 这里使用了lambda 实现了一个ObjectBeanFactory
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            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.
                            //最后从缓存中移除对应的实例原因有:
                            //1.每当有bean在创建时,允许循环参考来解析对应的beanDefinition
                            //2.删除临时引用该bean的bean
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    //获得一个 bean 实例
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                // 如果是常态多例的 bd
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        //在实例化之前执行一次 before
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        //实例化之后,执行一次 after
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
                //如果是其他scope
                else {
                    //获得 bean 的作用域
                    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, () -> {
                            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 && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return 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());
            }
        }
        //返回 bean
        return (T) bean;
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,589评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,615评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,933评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,976评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,999评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,775评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,474评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,359评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,854评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,007评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,146评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,826评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,484评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,029评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,153评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,420评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,107评论 2 356