Spring源码阅读(三)—IOC容器依赖注入

Spring源码阅读(三)—IOC容器依赖注入

IOC容器的初始化(Bean载入)和容器依赖注入是两个相对独立的过程.依赖注入一般发生在应用第一个通过getBean()方法向容器索取Bean的时候.

可以通过设置Bean的lazyinit属性实现Bean的预实例化,将这个Bean的依赖注入在在IOC容器初始化时候就完成.

个人主页:tuzhenyu’s page
原文地址:Spring源码阅读(三)—IOC容器依赖注入

(一) IOC容器依赖注入入口

从加载好的BeanFactory工厂中调用getBean()方法加载Bean,该方法会触发容器的依赖注入.


HelloBoy helloBoy = (HelloBoy)factory.getBean("boy");
helloBoy.sayHello();

(二) Bean的加载

getBean()方法的调用会触发AbstractBeanFactory的doGetBean()方法,该方法主要包括以下几部:

  • 尝试从缓存中取Bean

  • 如果缓存中不存在则创建Bean


protected  T doGetBean(String name, Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
    final String beanName = this.transformedBeanName(name);
    Object sharedInstance = this.getSingleton(beanName);    
     //从缓存中读取Bean
    Object bean;
    if(sharedInstance != null && args == null) {  
     //如果缓存中存在该Bean,则从缓存中加载该Bean
        if(this.logger.isDebugEnabled()) {
            if(this.isSingletonCurrentlyInCreation(beanName)) {
                this.logger.debug("Returning eagerly cached instance of singleton bean \'" + beanName + "\' that is not fully initialized yet - a consequence of a circular reference");
            } else {
                this.logger.debug("Returning cached instance of singleton bean \'" + beanName + "\'");
            }
        }

        bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
    } else {     
    //如果缓存中不存在该Bean,则创建该Bean
        if(this.isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        BeanFactory ex = this.getParentBeanFactory();
        if(ex != null && !this.containsBeanDefinition(beanName)) {
            String var24 = this.originalBeanName(name);
            if(args != null) {
                return ex.getBean(var24, args);
            }

            return ex.getBean(var24, requiredType);
        }

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

        try {
            final RootBeanDefinition ex1 = this.getMergedLocalBeanDefinition(beanName);
            this.checkMergedBeanDefinition(ex1, beanName, args);
            String[] dependsOn = ex1.getDependsOn();
            String[] scopeName;
            if(dependsOn != null) {
                scopeName = dependsOn;
                int scope = dependsOn.length;

                for(int ex2 = 0; ex2 < scope; ++ex2) {
                    String dependsOnBean = scopeName[ex2];
                    if(this.isDependent(beanName, dependsOnBean)) {
                        throw new BeanCreationException(ex1.getResourceDescription(), beanName, "Circular depends-on relationship between \'" + beanName + "\' and \'" + dependsOnBean + "\'");
                    }

                    this.registerDependentBean(dependsOnBean, beanName);
                    this.getBean(dependsOnBean);
                }
            }

            if(ex1.isSingleton()) {
                sharedInstance = this.getSingleton(beanName, new ObjectFactory() {
                    public Object getObject() throws BeansException {
                        try {
                            return AbstractBeanFactory.this.createBean(beanName, ex1, args);
                        } catch (BeansException var2) {
                            AbstractBeanFactory.this.destroySingleton(beanName);
                            throw var2;
                        }
                    }
                });
                bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, ex1);
            } else if(ex1.isPrototype()) {
                scopeName = null;

                Object var25;
                try {
                    this.beforePrototypeCreation(beanName);
                    var25 = this.createBean(beanName, ex1, args);
                } finally {
                    this.afterPrototypeCreation(beanName);
                }

                bean = this.getObjectForBeanInstance(var25, name, beanName, ex1);
            } else {
                String var26 = ex1.getScope();
                Scope var27 = (Scope)this.scopes.get(var26);
                if(var27 == null) {
                    throw new IllegalStateException("No Scope registered for scope \'" + var26 + "\'");
                }

                try {
                    Object var28 = var27.get(beanName, new ObjectFactory() {
                        public Object getObject() throws BeansException {
                            AbstractBeanFactory.this.beforePrototypeCreation(beanName);

                            Object var1;
                            try {
                                var1 = AbstractBeanFactory.this.createBean(beanName, ex1, args);
                            } finally {
                                AbstractBeanFactory.this.afterPrototypeCreation(beanName);
                            }

                            return var1;
                        }
                    });
                    bean = this.getObjectForBeanInstance(var28, name, beanName, ex1);
                } catch (IllegalStateException var21) {
                    throw new BeanCreationException(beanName, "Scope \'" + var26 + "\' 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", var21);
                }
            }
        } catch (BeansException var23) {
            this.cleanupAfterBeanCreationFailure(beanName);
            throw var23;
        }
    }

    if(requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
        try {
            return this.getTypeConverter().convertIfNecessary(bean, requiredType);
        } catch (TypeMismatchException var22) {
            if(this.logger.isDebugEnabled()) {
                this.logger.debug("Failed to convert bean \'" + name + "\' to required type [" + ClassUtils.getQualifiedName(requiredType) + "]", var22);
            }

            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    } else {
        return bean;
    }
}

(三) 从缓存中加载Bean

单例Bean在Spring的同一个容器中只会被创建一次,后续再获取bean都会直接从单例缓存中获取.单例缓存在DefaultSingletonBeanRegistry类的一个map型数据结构singletonObjects中.从缓存中取Bean时候如果singletonObjects缓存中存在则直接返回相应的Bean.

  • 如果缓存中不存在且通过isSingletonCurrentlyInCreation()方法知道该bean正在被创建则从earlySingletonObjects尝试获取

  • 如果earlySingletonObjects不存在则获取ObjectFactory类型的singletonFactory工厂,从singletonFactory中利用getObject()方法获取singleObject并将其放入earlySingletonObjects中,移除singletonFactories中的工厂singletonFactory.

  • earlySingletonObjects和singletonObjects都是用来保存beanName和bean实例之间的关系,与singletonObjects不同之处在于,当一个bean被放在这里面之后,当bean还在创建过程中,就可以通过getBean方法获取到,其目的是用来检测循环引用.




public Object getSingleton(String beanName) {
    return this.getSingleton(beanName, true);
}

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

    return singletonObject != NULL_OBJECT?singletonObject:null;
}

(四) 从Bean中获取对象

如果缓存中存在该bean,则可以直接取出.取出后可以通过getObjectForBeanInstance()方法从bean中获取对象.

  • 如果指定的name是工程相关的(以&开头)并且beanInstance不是FactoryBean类则验证不通过直接抛出错误.

  • 如果指定的name不是工程相关的(以&开头)并且beanInstance是FactoryBean类则从FactoryBean中解析出对象

  • 除了以上两种情况,直接返回beanInstance作为对象.




protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
    if(BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
        throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());
    } else if(beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
        Object object = null;
        if(mbd == null) {
            object = this.getCachedObjectForFactoryBean(beanName);
        }

        if(object == null) {
            FactoryBean factory = (FactoryBean)beanInstance;
            if(mbd == null && this.containsBeanDefinition(beanName)) {
                mbd = this.getMergedLocalBeanDefinition(beanName);
            }

            boolean synthetic = mbd != null && mbd.isSynthetic();
            object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
        }

        return object;
    } else {
        return beanInstance;
    }
}
  • 确认为FactoryBean确认完成后将从Factory中解析出bean对象的工作委托给getObjectFromFactoryBean()方法

getObjectFromFactoryBean()方法先查看缓存中是否存在该bean对象,如果不存在则委托给doGetObjectFromFactoryBean从FactoryBean中解析出bean对象.




protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
    if(factory.isSingleton() && this.containsSingleton(beanName)) {
        synchronized(this.getSingletonMutex()) {
            Object ex = this.factoryBeanObjectCache.get(beanName);
            if(ex == null) {
                ex = this.doGetObjectFromFactoryBean(factory, beanName);
                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                if(alreadyThere != null) {
                    ex = alreadyThere;
                } else {
                    if(ex != null && shouldPostProcess) {
                        try {
                            ex = this.postProcessObjectFromFactoryBean(ex, beanName);
                        } catch (Throwable var9) {
                            throw new BeanCreationException(beanName, "Post-processing of FactoryBean\'s singleton object failed", var9);
                        }
                    }

                    this.factoryBeanObjectCache.put(beanName, ex != null?ex:NULL_OBJECT);
                }
            }

            return ex != NULL_OBJECT?ex:null;
        }
    } else {
        Object object = this.doGetObjectFromFactoryBean(factory, beanName);
        if(object != null && shouldPostProcess) {
            try {
                object = this.postProcessObjectFromFactoryBean(object, beanName);
            } catch (Throwable var11) {
                throw new BeanCreationException(beanName, "Post-processing of FactoryBean\'s object failed", var11);
            }
        }

        return object;
    }
}
  • doGetObjectFromFactoryBean方法调用factory.getObject()方法获得bean对象



private Object doGetObjectFromFactoryBean(final FactoryBean factory, String beanName) throws BeanCreationException {
    Object object;
    try {
        if(System.getSecurityManager() != null) {
            AccessControlContext ex = this.getAccessControlContext();

            try {
                object = AccessController.doPrivileged(new PrivilegedExceptionAction() {
                    public Object run() throws Exception {
                        return factory.getObject();
                    }
                }, ex);
            } catch (PrivilegedActionException var6) {
                throw var6.getException();
            }
        } else {
            object = factory.getObject();
        }
    } catch (FactoryBeanNotInitializedException var7) {
        throw new BeanCurrentlyInCreationException(beanName, var7.toString());
    } catch (Throwable var8) {
        throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", var8);
    }

    if(object == null && this.isSingletonCurrentlyInCreation(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");
    } else {
        return object;
    }
}

(五) 创建Bean

从生成的ObjectFactory中获取bean

如果缓存中不存在已经加载的单例bean,就需要从头开始加载,Spring中通过getSingleton()的重载方法实现bean的加载过程.重载方法传入ObjectFactory参数,在getSingleton中调用objectFactory.getOBject()方法获取bean对象.getSingleton()主要操作内容包括:

  • 在beforeSingletonCreation()方法调用中将beanName加入singletonCurrentlyInCreation标记中,其他bean加载依赖时候如果发现该bean在singletonCurrentlyInCreation标记中则获取ObjectFactory放入earlySingletonObjects中.

  • 通过调用参数传入的ObjectFactory的getObject()方法实例化bean对象,在getObject()方法中会调用createBean()方法实例化bean.

  • 在afterSingletonCreation()方法调用中将beanName从singletonCurrentlyInCreation标记中去除

  • 将结果记录到bean缓存singletonObjects中,并删除加载bean过程中的所记录的各种辅助状态earlySingletonObjects,singletonFactories等.


public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
    Assert.notNull(beanName, "\'beanName\' must not be null");
    Map var3 = this.singletonObjects;
    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 the singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
            }

            if(this.logger.isDebugEnabled()) {
                this.logger.debug("Creating shared instance of singleton bean \'" + beanName + "\'");
            }

            this.beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = this.suppressedExceptions == null;
            if(recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet();
            }

            try {
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            } catch (IllegalStateException var16) {
                singletonObject = this.singletonObjects.get(beanName);
                if(singletonObject == null) {
                    throw var16;
                }
            } catch (BeanCreationException var17) {
                BeanCreationException ex = var17;
                if(recordSuppressedExceptions) {
                    Iterator var8 = this.suppressedExceptions.iterator();

                    while(var8.hasNext()) {
                        Exception suppressedException = (Exception)var8.next();
                        ex.addRelatedCause(suppressedException);
                    }
                }

                throw ex;
            } finally {
                if(recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }

                this.afterSingletonCreation(beanName);
            }

            if(newSingleton) {
                this.addSingleton(beanName, singletonObject);
            }
        }

        return singletonObject != NULL_OBJECT?singletonObject:null;
    }
}

生成的ObjectFactory,准备创建bean

  • 在ObjectFactory的getObject()方法中调用createBean()方法,用来创建bean

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    if(this.logger.isDebugEnabled()) {
        this.logger.debug("Creating instance of bean \'" + beanName + "\'");
    }

    this.resolveBeanClass(mbd, beanName, new Class[0]);

    try {
        mbd.prepareMethodOverrides();
    } catch (BeanDefinitionValidationException var5) {
        throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", var5);
    }

    Object beanInstance;
    try {
        beanInstance = this.resolveBeforeInstantiation(beanName, mbd);
        if(beanInstance != null) {
            return beanInstance;
        }
    } catch (Throwable var6) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var6);
    }

    beanInstance = this.doCreateBean(beanName, mbd, args);
    if(this.logger.isDebugEnabled()) {
        this.logger.debug("Finished creating instance of bean \'" + beanName + "\'");
    }

    return beanInstance;
}
  • createBean()方法通过调用doCreateBean()方法真正创建bean

    • 调用createBeanInstance()方法调用构造方法构造原始对象(未进行属性装载),将BeanDefinition转换为bean;

    • 判断是否需要提前曝光,如果需要则调用addSingleFactory()方法将原始bean的工厂添加到singletonFactories中.

    • 调用populateBean()方法对原始bean进行属性填充,如果依赖其他bean则会递归调用getBean()方法.


protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) {
    BeanWrapper instanceWrapper = null;
    if(mbd.isSingleton()) {
        instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    }

    if(instanceWrapper == null) {
        instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }

    final Object bean = instanceWrapper != null?instanceWrapper.getWrappedInstance():null;
    Class beanType = instanceWrapper != null?instanceWrapper.getWrappedClass():null;
    Object earlySingletonExposure = mbd.postProcessingLock;
    synchronized(mbd.postProcessingLock) {
        if(!mbd.postProcessed) {
            this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            mbd.postProcessed = true;
        }
    }

    boolean var19 = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
    if(var19) {
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Eagerly caching bean \'" + beanName + "\' to allow for resolving potential circular references");
        }

        this.addSingletonFactory(beanName, new ObjectFactory() {
            public Object getObject() throws BeansException {
                return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    Object exposedObject = bean;

    try {
        this.populateBean(beanName, mbd, instanceWrapper);
        if(exposedObject != null) {
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        }
    } catch (Throwable var17) {
        if(var17 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var17).getBeanName())) {
            throw (BeanCreationException)var17;
        }

        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var17);
    }

    if(var19) {
        Object ex = this.getSingleton(beanName, false);
        if(ex != null) {
            if(exposedObject == bean) {
                exposedObject = ex;
            } else if(!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                String[] dependentBeans = this.getDependentBeans(beanName);
                LinkedHashSet actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                String[] var12 = dependentBeans;
                int var13 = dependentBeans.length;

                for(int var14 = 0; var14 < var13; ++var14) {
                    String dependentBean = var12[var14];
                    if(!this.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.");
                }
            }
        }
    }

    try {
        this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
        return exposedObject;
    } catch (BeanDefinitionValidationException var16) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
    }
}

(六) 总结

  • IOC容器的初始化和容器的依赖注入是两个相对独立的过程,在容器初始化时不会进行依赖的注入.而是当调用getBean()方法获取bean实例的时候会进行依赖注入.

  • bean实例的获取分为两种形式:从缓存中获取和从头创建获取.

  • (1) 缓存中获取

    • 为了解决单例模式的循环依赖问题,spring采用三级缓存:singletonFactories,earlySingletonObjets,singletonObjects

    • 先尝试从singletonObjects中取出bean对应的singleObject,如果加载不成功则通过isSingletonCurrentlyInCreation标志位判断是否该bean正在被创建.如果正在被创建则为了解决循环依赖尝试从二级缓存earlySingletonObjects中取,如果一级缓存singletonObjects中没有该bean并且也没有正在被创建,则从头创建该bean.

    • 尝试从二级缓存earlySingletonObjects中加载该bean对应的singletonObject,如果加载失败则尝试从三级缓存singletonFactories中加载singletonObject对应的工程singletonFactory,并调用getObject()方法获取singletonObject放入二级缓存earlySingletonObjets中,并删除三级缓存singletonFactories中的相应缓存.

    • 从bean实例singletonObject中调用getObjectForBeanInstance()方法获取对象,判断是否为FactoryBean类型,如果是则调用getObject()方法获取对象.

  • (2) 从头创建

    • 从头创建Bean的方法入口在重载的getSingletion(),包含工厂类参数ObjectFactory从中调用getObject获取bean实例.

    • getSingletion()方法首先调用beforeSingletonCreation()方法,在该方法中添加该bean的isSingletonCurrentlyInCreation标志位

    • 接着调用getObject()方法获取bean实例,getObject()方法中包含bean创建的方法入口createBean()方法.

      • createBean()方法调用doCreateBean()方法真正创建bean

      • 首先调用createBeanInstance()方法,就是调用对应的构造方法构造对象,此时只是调用了构造方法创建出的最原始的bean实例,如果在构造器创建原始bean的过程中出现循环依赖则会抛出循环依赖错误.

      • 判断时候需要提前曝光(单例&允许循环依赖&存在isSingletonCurrentlyInCreation标志位),如果需要则调用addSingletonFactory()方法将构造器创建原始bean实例封装后放入三级缓存singletonFactories中.

      • 调用populateBean()方法对原始bean进行属性填充

      • 完成创建并返回bean实例

    • 接着调用afterSingletonCreation()方法删除该bean的isSingletonCurrentlyInCreation标志位

    • 最后调用addSingleton()方法将获取的bean实例放入一级缓存singtonObjects,并从二级缓存earlySingletonObjets和三级缓存singletonFactories中删除对应的bean.

你可能感兴趣的:(spring,Spring源码阅读,spring,源码)