美文网首页
Spring-IOC实例化源码解析(4)2018-08-01

Spring-IOC实例化源码解析(4)2018-08-01

作者: Seetheworl_6675 | 来源:发表于2018-08-02 20:53 被阅读0次

      之前我们演示一个简单的IOC案例,并分析了部分涉及到的类的继承结构,今天我们正式进入到IOC源码的解析。Spring的IoC容器可以按照类似的流程划分为两个阶段,即容器启动阶段和Bean实例化阶段。上一篇Spring-IOC(3)我们了解了启动阶段,接下来看看实例化阶段:

    Bean实例化阶段:

      该阶段,容器会首先检查所请求的对象之前是否已经初始化。如果没有,则会根据注册的BeanDefinition所提供的信息实例化被请求对象,并为其注入依赖。如果该对象实现了某些回调接 口,也会根据回调接口的要求来装配它。当该对象装配完毕之后,容器会立即将其返回请求方使用。

    触发实例化:

     当某个请求方通过容器的getBean方法明确地请求某个对象,或者因依赖关系容器需要隐式地调用getBean方法时,将触发Bean实例化。

     1、接下来我们依旧从Spring-IOC(1)案例的测试类入手:

    测试类
     2、getBean处触发了Bean的实例化 getBean

     3、接着往doGetBean里面看:

        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;
    
    
            /**
             * spring会先检查缓存中或者实例工厂中是否有对应的实例,因为在创建单例bean的时候回存在循环注入的情况;
             * 而在创建以来的时候为了避免循环依赖,spring创建bean的原则是不等bean创建完成就会将创建bean的 objectfactory提前曝光,
             * 也就是将objectFactory加入到缓存中,一旦下一个bean创建的时候需要依赖上个bean则直接使用objectfactory;
             */
            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 + "'");
                    }
                }
                //获取给定Bean的实例对象,主要是完成FactoryBean的相关处理
                // (name 是以&开头的返回FactoryBean本身,否则调用factory.getObject获取对象)
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
            }
    
            else {
                //缓存中已经有已经创建的原型模式Bean,但是由于循环引用的问题导致实实例化失败
                //说明spring中对循环依赖的情况也是无能为力
                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) {
                        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 {
                        // No args -> delegate to standard getBean method.
                        //委派父级容器根据指定名称和类型查找
                        return parentBeanFactory.getBean(nameToLookup, requiredType);
                    }
                }
                //创建的Bean是否需要进行类型验证,一般不需要
                if (!typeCheckOnly) {
                    //向容器标记指定的Bean已经被创建
                    markBeanAsCreated(beanName);
                }
    
                try {
                    //根据指定Bean名称获取其父级的Bean定义,主要解决Bean继承时子类
                    //合并父类公共属性问题
                    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                    checkMergedBeanDefinition(mbd, beanName, args);
    
                    // Guarantee initialization of beans that the current bean depends on.
                    //获取当前Bean所有依赖Bean的名称
                    String[] dependsOn = mbd.getDependsOn();
                    //如果当前Bean有依赖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注册给当前依赖的Bea
                            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);
                            }
                        }
                    }
    
                    // Create bean instance.
                    //创建单态模式Bean的实例对象
                    if (mbd.isSingleton()) {
                        //这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
                        sharedInstance = getSingleton(beanName, () -> {
                            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的实例对象
                        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                    }
                    //IoC容器创建原型模式Bean实例对象
                    else if (mbd.isPrototype()) {
                        // It's a prototype -> create a new instance.
                        Object prototypeInstance = null;
                        try {
                            //回调beforePrototypeCreation方法,
                            beforePrototypeCreation(beanName);
                            //创建指定Bean对象实例
                            prototypeInstance = createBean(beanName, mbd, args);
                        }
                        finally {
                            //回调afterPrototypeCreation方法
                            afterPrototypeCreation(beanName);
                        }
                        bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                    }
                    //要创建的Bean既不是单态模式,也不是原型模式,则根据Bean定义资源中
                    //配置的生命周期范围,选择实例化Bean的合适方法,这种在Web应用程序中
                    //比较常用,如:request、session、application等生命周期
                    else {
                        String scopeName = mbd.getScope();
                        final 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 = 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;
                }
            }
            //对创建的Bean实例对象进行类型检查
            // 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.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;
        }
    

     通过上面对向IoC容器获取Bean方法的分析,我们可以看到在Spring中,如果Bean定义的单态模式(Singleton),则容器在创建之前先从缓存中查找,以确保整个容器中只存在一个实例对象。如果Bean定义的是原型模式(Prototype),则容器每次都会创建一个新的实例对象。除此之外,Bean定义还可以扩展为指定其生命周期范围。

     上面的源码只是定义了根据Bean定义的模式,采取的不同创建Bean实例对象的策略,具体的Bean实例对象的创建过程由实现了ObejctFactory接口的匿名内部类的createBean方法完成,ObejctFactory使用委派模式,具体的Bean实例创建过程交由其实现类AbstractAutowireCapableBeanFactory完成,我们继续分析AbstractAutowireCapableBeanFactory的createBean方法的源码,理解其创建Bean实例的具体实现过程。

     4、我们的测试案例为例创建的是单例bean则将执行getSingleton方法:

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
            //判空
            Assert.notNull(beanName, "Bean name must not be null");
            synchronized (this.singletonObjects) {
                Object singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    //单例对象正在被销毁 则抛异常
                    if (this.singletonsCurrentlyInDestruction) {
                        throw new BeanCreationNotAllowedException(beanName,
                                "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                                "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                    }
                    if (logger.isDebugEnabled()) {
                        logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                    }
                    //前置处理 这里会标记对象为正在创建中
                    beforeSingletonCreation(beanName);
                    boolean newSingleton = false;
                    boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = new LinkedHashSet<>();
                    }
                    try {
                        //创建对象
                        singletonObject = singletonFactory.getObject();
                        newSingleton = true;
                    }
                    catch (IllegalStateException ex) {
                        // Has the singleton object implicitly appeared in the meantime ->
                        // if yes, proceed with it since the exception indicates that state.
                        singletonObject = this.singletonObjects.get(beanName);
                        if (singletonObject == null) {
                            throw ex;
                        }
                    }
                    catch (BeanCreationException ex) {
                        if (recordSuppressedExceptions) {
                            for (Exception suppressedException : this.suppressedExceptions) {
                                ex.addRelatedCause(suppressedException);
                            }
                        }
                        throw ex;
                    }
                    finally {
                        if (recordSuppressedExceptions) {
                            this.suppressedExceptions = null;
                        }
                        //后置处理 这里将移除对象正在创建的缓存
                        afterSingletonCreation(beanName);
                    }
                    if (newSingleton) {
                         //缓存处理
                        addSingleton(beanName, singletonObject);
                    }
                }
                return singletonObject;
            }
        }
    
    

     这里先从缓存中获取对象,为空时前置处理创建bean实例的状态设置和校验(判断当前bean不在创建中,singletonsCurrentlyInCreation缓存中添加当前beanName),后调用工厂getObject获取对象,最后处理singletonsCurrentlyInCreation缓存中移除当前beanName)并且处理bean的缓存。
     5、调用工厂getObject后执行createBean方法:

    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                throws BeanCreationException {
    
            if (logger.isDebugEnabled()) {
                logger.debug("Creating instance of bean '" + beanName + "'");
            }
            RootBeanDefinition mbdToUse = mbd;
    
            // Make sure bean class is actually resolved at this point, and
            // clone the bean definition in case of a dynamically resolved Class
            // which cannot be stored in the shared merged bean definition.
            //判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载 
            Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
            if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
                mbdToUse = new RootBeanDefinition(mbd);
                mbdToUse.setBeanClass(resolvedClass);
            }
    
            // Prepare method overrides.
            try {
                //校验和准备Bean中的方法覆盖 
                mbdToUse.prepareMethodOverrides();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                        beanName, "Validation of method overrides failed", ex);
            }
    
            try {
                // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                 //如果Bean配置了实例化前的处理器,则试图返回一个需要创建Bean的代理对象
                Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
                if (bean != null) {
                    return bean;
                }
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                        "BeanPostProcessor before instantiation of bean failed", ex);
            }
    
            try {
                //创建Bean的入口
                Object beanInstance = doCreateBean(beanName, mbdToUse, args);
                if (logger.isDebugEnabled()) {
                    logger.debug("Finished creating instance of bean '" + beanName + "'");
                }
                return beanInstance;
            }
            catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
                // A previously detected exception with proper bean creation context already,
                // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanCreationException(
                        mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
            }
        }
    

     这里在实例化给BeanPostProcessors提供返回代理而不是目标bean实例的机会。
     6、我们接着看doCreateBean:

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
                throws BeanCreationException {
    
            // Instantiate the bean.
            //封装被创建的Bean对象
            BeanWrapper instanceWrapper = null;
            if (mbd.isSingleton()) {
                //单态模式的Bean,先从容器中缓存中获取同名Bean 
                instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
            }
            if (instanceWrapper == null) {
                 //创建封装实例对象
                instanceWrapper = createBeanInstance(beanName, mbd, args);
            }
            //实例对象
            final Object bean = instanceWrapper.getWrappedInstance();
            //获取实例化对象的类型
            Class<?> beanType = instanceWrapper.getWrappedClass();
            if (beanType != NullBean.class) {
                mbd.resolvedTargetType = beanType;
            }
    
            // Allow post-processors to modify the merged bean definition.
            //调用BeanDefinitionPostProcessor前置处理器
            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.
            boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                    isSingletonCurrentlyInCreation(beanName));
             //向容器中缓存单态模式的Bean对象,以防循环引用 
            if (earlySingletonExposure) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Eagerly caching bean '" + beanName +
                            "' to allow for resolving potential circular references");
                }
                addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
            }
    
            // Initialize the bean instance.
            //初始化bean
            Object exposedObject = bean;
            try {
                //Bean定义中配置的属性值赋值给实例对象
                populateBean(beanName, mbd, instanceWrapper);
              //初始化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);
                }
            }
      
            if (earlySingletonExposure) {
                  //获取指定名称的已注册的单态模式Bean对象  
                Object earlySingletonReference = getSingleton(beanName, false);
                if (earlySingletonReference != null) {
                     //根据名称获取的以注册的Bean和正在实例化的Bean是同一个 
                    if (exposedObject == bean) {
                        exposedObject = earlySingletonReference;
                    }
                      //当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象  
                    else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                        String[] dependentBeans = getDependentBeans(beanName);
                        Set<String> actualDependentBeans = new LinkedHashSet<>(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.
            //注册完成依赖注入的Bean  注册到disposableBeans中
            try {
                registerDisposableBeanIfNecessary(beanName, bean, mbd);
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
            }
    
            return exposedObject;
        }
    

     到此一个单例的实例化算是完成了,但是我们源码的解析不全部,有待慢慢细化,这里我们在总结下Spring是如何处理依赖循环的:
     先下面连个代码段:

     代码片段1、在doGetBean方法中Object sharedInstance = getSingleton(beanName)这个方法:

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
                synchronized (this.singletonObjects) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null && allowEarlyReference) {
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
            return singletonObject;
        }
    

     a、singletonObjects : 用于保存beanName和创建bean实例之间的关系
     b、singletonFactories : 用于保存beanName和创建bean的工厂之间的关系
     c、earlySingletonObjects :也是保存beanName和bean实例之间的关系,与singletonObjects 的不同之处在于,当一个单例bean被放在这里后,那么当bean还在创建过程中,就可以通过getBean的方法获取了,其目的是用来检测循环引用。

     代码片段2、在doCreateBean中:

    // Eagerly cache singletons to be able to resolve circular references
            // even when triggered by lifecycle interfaces like BeanFactoryAware.
            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, () -> getEarlyBeanReference(beanName, mbd, bean));
            }
    
    // Eagerly cache singletons to be able to resolve circular references
            // even when triggered by lifecycle interfaces like BeanFactoryAware.
            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, () -> getEarlyBeanReference(beanName, mbd, bean));
            }
    
    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
            Assert.notNull(singletonFactory, "Singleton factory must not be null");
            synchronized (this.singletonObjects) {
                if (!this.singletonObjects.containsKey(beanName)) {
                    this.singletonFactories.put(beanName, singletonFactory);
                    this.earlySingletonObjects.remove(beanName);
                    this.registeredSingletons.add(beanName);
                }
            }
        }
    

     从以上两段代码:结合测试案例(刚好我们测试案例也符合就是一个循环依赖的案例),我们来解析下循环依赖:

     从之前的源码解析我们很容易明白bean创建对象需要经历以下三个阶段先来了解下:


    image.png

     在代码片段一从singletonFactories.getObject()和earlySingletonObjects缓存中返回的对象其实就Bean创建的第一阶段不完整的实例对象。


    循环依赖程序流程图
     决循环依赖的关键,这段代码发生在createBeanInstance之后,也就是说单例对象此时已经被创建出来(调用了构造器)。这个对象已经被生产出来了,虽然还不完美(还没有进行初始化的第二步和第三步),但是已经能被人认出来了(根据对象引用能定位到堆中的对象),所以Spring此时将这个对象提前曝光出来让大家认识,让大家使用。
     知道了这个原理时候,肯定就知道为啥Spring不能解决“A的构造方法中依赖了B的实例对象,同时B的构造方法中依赖了A的实例对象”这类问题了!因为加入singletonFactories三级缓存的前提是执行了构造器,所以构造器的循环依赖没法解决。

    相关文章

      网友评论

          本文标题:Spring-IOC实例化源码解析(4)2018-08-01

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