Spring源码阅读(三)—IOC容器依赖注入
2017-08-30 13:51
886 查看
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> T doGetBean(String name, Class<T> 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.get 1311a MergedLocalBeanDefinition(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()方法,用来创建beanprotected 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源码--IOC容器的实现】(六)Bean的依赖注入
- Ioc容器依赖注入-Spring 源码系列(2)
- Spring:源码解读(IOC容器的依赖注入)
- 8-spring源码3.2.18解读+spring技术内幕(IOC容器的依赖注入(反射+递归调用))
- Spring应用、原理以及粗读源码系列(一)--框架总述、以Bean为核心的机制(IoC容器初始化以及依赖注入)
- Spring IOC源码详解之容器依赖注入
- Ioc容器依赖注入-Spring 源码(2)
- Spring源码解析三:IOC容器的依赖注入
- Spring源码学习IOC(5):IOC容器的依赖注入
- 深入研究Spring-IoC:源码分析依赖注入
- Spring源码阅读之IoC容器初始化1 -- Resource定位
- SpringIOC容器创建对象及依赖注入的几种方式
- Spring源码阅读-- IOC容器资源解析
- Spring源码阅读-- IOC容器资源定位
- Spring源码阅读:IOC容器的设计与实现(二)——ApplicationContext
- 浅谈Spring IoC容器的依赖注入原理
- Spring源码阅读之IoC容器初始化2 -- BeanDefinition载入与解析
- Spring IoC容器在Web环境中的启动源码阅读
- Spring Ioc容器依赖注入
- Spring源码分析----IOC依赖注入