美文网首页spring
Spring(五)Spring Bean加载过程详解

Spring(五)Spring Bean加载过程详解

作者: Colors_boy | 来源:发表于2021-01-23 14:33 被阅读0次

    前言

    通过之前篇章的解析,已经是把xml配置文件解析完成并把bean所有的元数据信息存放到BeanDefinition当中,在工厂底层使用了键为beamName,值为beanDefinition的ConcurrentHashMap来做保存。但这个阶段创建的只是 beanDefinition 而不是一个实例,即bean并没有实例化。我们想要调用Bean则需要通过BeanFactory.getBean()方法来获取bean的实例。

    BeanFactory.getBean()

    经过源码追踪,本质上是使用过 AbstractBeanFactory.getBean() 来获取实例:

        @Override
        public Object getBean(String name) throws BeansException {
            return doGetBean(name, null, null, false);
        }
    
        @Override
        public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
            return doGetBean(name, requiredType, null, false);
        }
    
        @Override
        public Object getBean(String name, Object... args) throws BeansException {
            return doGetBean(name, null, args, false);
        }
    

    从这里发现,无论是哪种传参,都是调用了 doGetBean() 方法,所以 doGetBean() 方法是核心方法。

    doGetBean()

            protected <T> T doGetBean(
                String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
                throws BeansException {
    
            // 1. 返回Bean名称,必要时去除工厂取消引用前缀,并将别名解析为规范名称
            String beanName = transformedBeanName(name);
            Object beanInstance;
    
            /**
             *  解决循环依赖
             * 尝试以singleton的方式调用DefaultSingletonBeanRegistry.getSingleton(String)获取bean,
             * 这个方法还会以allowEarlyReference=true即允许早期引用的形式继续调用getSingleton(String beanName,
             * boolean allowEarlyReference)。
             * 该方法会先从一级缓存singletonObjects以及二级缓存earlySingletonObjects中获取,
             * 若依然获取不到,由于allowEarlyReference=true,则会继续从三级缓存singletonFactories中获取objectFactorys,
             * 若获取到了就以objectFactory#getObject的方式获取bean。 执行过程可能是以下的几种情况:
             * 1、从一级缓存singletonObjects中获取bean,若获取到了说明获取的bean早就被创建好了,否则继续获取
             * 2、一级缓存未获取到,继续从二级缓存earlySingletonObjects中获取,若获取到了,说明该beanName虽然已被创建完毕,
             * 但还非完全实例化完毕(singletonsCurrentlyInCreation中必然存在该beanName),
             * 只是提早暴露了出来而已。(而之所以会在二级缓存earlySingletonObjects中,请看(3))
             * 3、一级、二级缓存中都未获取到,且allowEarlyReference=true的时候,从三级缓存singletonFactories中获取,
             * 获取到的是objectFactory,若获取到了,说明当前beanName正在创建中,尚未完全创建完毕,
             * 只是提前将自己的制造工厂——ObjectFactory暴露出来了而已,然后继续调用ObjectFactory#getObject获取bean,
             * 一般而言,这里的ObjectFactory#getObject都是在AbstractAutowireCapableBeanFactory.doCreateBean中添加的,
             * 且getObject方法是调用AbstractAutowireCapableBeanFactory.getEarlyBeanReference获取早期引用的。
             * 4、三级缓存中也没有获取到,说明当前bean尚未被加载过,方法执行完毕,doGetBean继续向下执行。
             */
            Object sharedInstance = getSingleton(beanName);
              /**
             * 根据之前的getSingleton(String)是否从缓存中获取到了bean决定如何执行:
             * 1、若获取到了,则继续调用AbstractBeanFactory.getObjectForBeanInstance判断该类是否实现了FactoryBean,
             * 若实现了则调用getObject获取bean,否则依然返回bean。 2、若未获取到则说明该bean尚未被初始化或者其根本就不是单例而是多例,继续执行下去
             */
            if (sharedInstance != null && args == null) {
                if (logger.isTraceEnabled()) {
                    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 + "'");
                    }
                }
                beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
            }
    
            else {
                 /*
                  *判断是否正处于创建的过程中,防止同时创建
                  */
                if (isPrototypeCurrentlyInCreation(beanName)) {
                    throw new BeanCurrentlyInCreationException(beanName);
                }
    
                // 在父工厂中检查是否存在装配好的 beanDefinition 并从中获取
                BeanFactory parentBeanFactory = getParentBeanFactory();
                if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                    String nameToLookup = originalBeanName(name);
                    if (parentBeanFactory instanceof AbstractBeanFactory) {
                        return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                                nameToLookup, requiredType, args, typeCheckOnly);
                    }
                    else if (args != null) {
                        // Delegation to parent with explicit args.
                        return (T) parentBeanFactory.getBean(nameToLookup, args);
                    }
                    else if (requiredType != null) {
                        // No args -> delegate to standard getBean method.
                        return parentBeanFactory.getBean(nameToLookup, requiredType);
                    }
                    else {
                        return (T) parentBeanFactory.getBean(nameToLookup);
                    }
                }
    
                 /**
                 * 用来标记当前bean是否已被创建完毕的方法,若当前bean尚未被创建,则执行完该方法,
                 * 其就会被加入到AbstractBeanFactory.alreadyCreated中,表示该bean已被创建或即将被创建。
                 *通过 双重检测 校验 bean 是否处于创建或即将被创建
                 */
                if (!typeCheckOnly) {
                    markBeanAsCreated(beanName);
                }
    
                StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
                        .tag("beanName", name);
                try {
                    if (requiredType != null) {
                        beanCreation.tag("beanType", requiredType::toString);
                    }
                    // 通过键 benaName 从map中获取装配好的 beanDifinition 信息
                    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                    checkMergedBeanDefinition(mbd, beanName, args);
    
                    /**
                     * 获取该bean的依赖,若存在,则逐个以DefaultSingletonBeanRegistry.registerDependentBean添加到dependentBeanMap中
                     * 并通过AbstractBeanFactory.getBean(String)保证当前Bean依赖的Bean全部被初始化,所以递归getBean。
                     */
                    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 + "'");
                            }
                            registerDependentBean(dep, beanName);
                            try {
                                // 如果A依赖于B,则需要把B先创建出来,A处于创建或即将被创建状态,并放置在三级缓存(singletonFactories)当中,当B创建好后,将A提升至二级缓存
                                getBean(dep);
                            }
                            catch (NoSuchBeanDefinitionException ex) {
                                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                            }
                        }
                    }
    
                     /**
                     * 若是单例,则调用DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory<?>),
                     * 同时通过内部类的方式重写了ObjectFactory#getObject,
                     * 其会先从缓存DefaultSingletonBeanRegistry#singletonObjects中获取,
                     * 获取不到则说明该bean还未被实例化,以ObjectFactory#getObject继续获取该bean实例,
                     * 然后以匿名内部类的方式调用AbstractBeanFactory#createBean进行创建bean的操作,
                     * 实例化完成后,调用DefaultSingletonBeanRegistry#addSingleton将其放入缓存map-singletonObjects中,
                     * 这样之后调用就不会再创建了
                     */
                    if (mbd.isSingleton()) {
                        sharedInstance = getSingleton(beanName, () -> {
                            try {
                                // 通过反射的方式创建Bean实例对属性设值并放到singletonObjects缓存当中
                                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;
                            }
                        });
                        beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                    }
    
                    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);
                        }
                        beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                    }
    
                    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);
                        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);
                                }
                            });
                            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) {
            // Check if required type matches the type of the actual bean instance.
            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;
        }
    

    相关文章

      网友评论

        本文标题:Spring(五)Spring Bean加载过程详解

        本文链接:https://www.haomeiwen.com/subject/igquzktx.html