博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring源码解析之IOC容器(三)——依赖注入
阅读量:7079 次
发布时间:2019-06-28

本文共 21565 字,大约阅读时间需要 71 分钟。

  上一篇主要是跟踪了IOC容器对bean标签进行解析之后存入Map中的过程,这些bean只是以BeanDefinition为载体单纯的存储起来了,并没有转换成一个个的对象,今天继续进行跟踪,看一看IOC容器是怎样实例化对象的。

  我们都使用过以下代码:

1 FileSystemXmlApplicationContext  context=new FileSystemXmlApplicationContext("bean.xml");2 User user=context.getBean("user",User.class);

  这样我们就能获取到user对象了,所以,不难想象,这个getBean方法就是实例化对象的入口。接下来我们就以这个方法为切入点,来探究IOC容器中bean的实例化过程。getBean方法是在FileSystemXmlApplicationContext的基类AbstractApplicationContext中定义的,代码如下:

1 public 
T getBean(String name, Class
requiredType) throws BeansException {2 assertBeanFactoryActive();3 return getBeanFactory().getBean(name, requiredType);4 }

  里面有很多重载方法,里面有调用了某个beanFactory的getBean方法。AbstractApplicationContext中并没有定义getBeanFactory这个方法,那一定是在FileSystemXmlApplicatio

—ntext的某个父类中定义的,我们再回过头看一下它的UML图:

  经过查找之后,是在AbstractRefreshableApplicationContext中定义的,且这个beanFactory是DefaultListableBeanFactory类型的:

1 public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext { 2  3     private Boolean allowBeanDefinitionOverriding; 4  5     private Boolean allowCircularReferences; 6  7     /** Bean factory for this context */ 8     private DefaultListableBeanFactory beanFactory; 9 10     /** Synchronization monitor for the internal BeanFactory */11     private final Object beanFactoryMonitor = new Object();

  直接进入DefaultListableBeanFactory中,查看它的getBean方法:

public 
T getBean(Class
requiredType) throws BeansException { return getBean(requiredType, (Object[]) null); }
public 
T getBean(Class
requiredType, Object... args) throws BeansException { NamedBeanHolder
namedBean = resolveNamedBean(requiredType, args); if (namedBean != null) { return namedBean.getBeanInstance(); } BeanFactory parent = getParentBeanFactory(); if (parent != null) { return parent.getBean(requiredType, args); } throw new NoSuchBeanDefinitionException(requiredType); }

  发现里面只有这两个重载方法,其他getBean方法,包括例子中使用的那个重载方法没有看到,我们看一下DefaultListableBeanFactory类的UML图:

  经查找,发现在父类AbstractBeanFactory中定义了其他的getBean方法,如下:

1 public Object getBean(String name, Object... args) throws BeansException {2         return doGetBean(name, null, args, false);3     }
1 public 
T getBean(String name, Class
requiredType, Object... args) throws BeansException {2 return doGetBean(name, requiredType, args, false);3 }

  里面都调用了doGetBean方法,那么进入继续跟踪:

1 protected 
T doGetBean( 2 final String name, final Class
requiredType, final Object[] args, boolean typeCheckOnly) 3 throws BeansException { 4 //将bean的name进行转换,比如将name前面的“&”符去掉,带“&”的name,获取的是beanFactory本身,而不是 5 //beanFactory生成出来的bean实例 6 final String beanName = transformedBeanName(name); 7 Object bean; 8 9 // Eagerly check singleton cache for manually registered singletons. 10 //看缓存中是否已经有该bean 11 Object sharedInstance = getSingleton(beanName); 12 //如果缓存中有 13 if (sharedInstance != null && args == null) { 14 if (logger.isDebugEnabled()) { 15 if (isSingletonCurrentlyInCreation(beanName)) { 16 logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + 17 "' that is not fully initialized yet - a consequence of a circular reference"); 18 } 19 else { 20 logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); 21 } 22 } 23 //如果sharedInstance是FactoryBean类型,则返回它生产的对象,否则,返回它本身 24 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 25 } 26 //如果缓存中没有,第一次创建的时候 27 else { 28 // Fail if we're already creating this bean instance: 29 // We're assumably within a circular reference. 30 if (isPrototypeCurrentlyInCreation(beanName)) { 31 throw new BeanCurrentlyInCreationException(beanName); 32 } 33 34 // Check if bean definition exists in this factory. 35 //获取父容器 36 BeanFactory parentBeanFactory = getParentBeanFactory(); 37 //如果父容器存在,且在当前容器中没有找到该名称的bean的数据 38 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 39 //则到父容器中进行处理 40 // Not found -> check parent. 41 //将name前加上“&” 42 String nameToLookup = originalBeanName(name); 43 //分别对是否有参数的情况进行处理 44 if (args != null) { 45 // Delegation to parent with explicit args. 46 return (T) parentBeanFactory.getBean(nameToLookup, args); 47 } 48 else { 49 // No args -> delegate to standard getBean method. 50 return parentBeanFactory.getBean(nameToLookup, requiredType); 51 } 52 } 53 54 if (!typeCheckOnly) { 55 markBeanAsCreated(beanName); 56 } 57 58 try { 59 //将数据封装成RootBeanDefinition对象 60 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 61 //检查是否为抽象类 62 checkMergedBeanDefinition(mbd, beanName, args); 63 64 // Guarantee initialization of beans that the current bean depends on. 65 //获取当前创建的bean的依赖的bean 66 String[] dependsOn = mbd.getDependsOn(); 67 if (dependsOn != null) { 68 for (String dep : dependsOn) { 69 if (isDependent(beanName, dep)) { 70 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 71 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); 72 } 73 //为当前bean和它的依赖对象建立映射关系 74 registerDependentBean(dep, beanName); 75 try { 76 //递归调用getBean方法,创建依赖对象,直到没有依赖对象为止 77 getBean(dep); 78 } 79 catch (NoSuchBeanDefinitionException ex) { 80 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 81 "'" + beanName + "' depends on missing bean '" + dep + "'", ex); 82 } 83 } 84 } 85 86 // Create bean instance. 87 if (mbd.isSingleton()) { 88 sharedInstance = getSingleton(beanName, new ObjectFactory
() { 89 @Override 90 public Object getObject() throws BeansException { 91 try { 92 //回调方法 93 return createBean(beanName, mbd, args); 94 } 95 catch (BeansException ex) { 96 // Explicitly remove instance from singleton cache: It might have been put there 97 // eagerly by the creation process, to allow for circular reference resolution. 98 // Also remove any beans that received a temporary reference to the bean. 99 destroySingleton(beanName);100 throw ex;101 }102 }103 });104 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);105 }106 107 else if (mbd.isPrototype()) {108 // It's a prototype -> create a new instance.109 Object prototypeInstance = null;110 try {111 beforePrototypeCreation(beanName);112 prototypeInstance = createBean(beanName, mbd, args);113 }114 finally {115 afterPrototypeCreation(beanName);116 }117 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);118 }119 120 else {121 String scopeName = mbd.getScope();122 final Scope scope = this.scopes.get(scopeName);123 if (scope == null) {124 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");125 }126 try {127 Object scopedInstance = scope.get(beanName, new ObjectFactory() {128 @Override129 public Object getObject() throws BeansException {130 beforePrototypeCreation(beanName);131 try {132 return createBean(beanName, mbd, args);133 }134 finally {135 afterPrototypeCreation(beanName);136 }137 }138 });139 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);140 }141 catch (IllegalStateException ex) {142 throw new BeanCreationException(beanName,143 "Scope '" + scopeName + "' is not active for the current thread; consider " +144 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",145 ex);146 }147 }148 }149 catch (BeansException ex) {150 cleanupAfterBeanCreationFailure(beanName);151 throw ex;152 }153 }154 155 // Check if required type matches the type of the actual bean instance.156 if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {157 try {158 return getTypeConverter().convertIfNecessary(bean, requiredType);159 }160 catch (TypeMismatchException ex) {161 if (logger.isDebugEnabled()) {162 logger.debug("Failed to convert bean '" + name + "' to required type '" +163 ClassUtils.getQualifiedName(requiredType) + "'", ex);164 }165 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());166 }167 }168 return (T) bean;169 }

  可以看到对不同scope域的bean的创建过程,其中会进行递归创建,现在进入createBean方法中,其实现是在AbstractAutowireCapableBeanFactory类中,代码如下:

1 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { 2         if (logger.isDebugEnabled()) { 3             logger.debug("Creating instance of bean '" + beanName + "'"); 4         } 5         RootBeanDefinition mbdToUse = mbd; 6  7         // Make sure bean class is actually resolved at this point, and 8         // clone the bean definition in case of a dynamically resolved Class 9         // which cannot be stored in the shared merged bean definition.10         //判断需要创建的bean是否可以实例化,是否可以通过类装载其进行装载11         Class
resolvedClass = resolveBeanClass(mbd, beanName);12 if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {13 mbdToUse = new RootBeanDefinition(mbd);14 mbdToUse.setBeanClass(resolvedClass);15 }16 17 // Prepare method overrides.18 try {19 //这里是对overrides属性和look-up属性的处理20 mbdToUse.prepareMethodOverrides();21 }22 catch (BeanDefinitionValidationException ex) {23 throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),24 beanName, "Validation of method overrides failed", ex);25 }26 27 try {28 //AOP就是这里操作的,如果配置了postProcessor,则生成一个proxy返回,即代理类29 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.30 Object bean = resolveBeforeInstantiation(beanName, mbdToUse);31 if (bean != null) {32 return bean;33 }34 }35 catch (Throwable ex) {36 throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,37 "BeanPostProcessor before instantiation of bean failed", ex);38 }39 //创建bean的方法调用40 Object beanInstance = doCreateBean(beanName, mbdToUse, args);41 if (logger.isDebugEnabled()) {42 logger.debug("Finished creating instance of bean '" + beanName + "'");43 }44 return beanInstance;45 }

  进入doCreateBean方法:

1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)  2             throws BeanCreationException {  3   4         // Instantiate the bean.  5         BeanWrapper instanceWrapper = null;  6         if (mbd.isSingleton()) {  7             //如果是单例,先把缓存中的同名Bean清除  8             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);  9         } 10         //如果缓存中没有 11         if (instanceWrapper == null) { 12             //则创建一个实例 13             instanceWrapper = createBeanInstance(beanName, mbd, args); 14         } 15         final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); 16         Class
beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); 17 mbd.resolvedTargetType = beanType; 18 19 // Allow post-processors to modify the merged bean definition. 20 synchronized (mbd.postProcessingLock) { 21 if (!mbd.postProcessed) { 22 try { 23 //使用后置处理器进行处理 24 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 25 } 26 catch (Throwable ex) { 27 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 28 "Post-processing of merged bean definition failed", ex); 29 } 30 mbd.postProcessed = true; 31 } 32 } 33 34 // Eagerly cache singletons to be able to resolve circular references 35 // even when triggered by lifecycle interfaces like BeanFactoryAware. 36 //这里是对单例的循环引用的处理 37 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && 38 isSingletonCurrentlyInCreation(beanName)); 39 if (earlySingletonExposure) { 40 if (logger.isDebugEnabled()) { 41 logger.debug("Eagerly caching bean '" + beanName + 42 "' to allow for resolving potential circular references"); 43 } 44 addSingletonFactory(beanName, new ObjectFactory() { 45 @Override 46 public Object getObject() throws BeansException { 47 return getEarlyBeanReference(beanName, mbd, bean); 48 } 49 }); 50 } 51 52 //这里是对bean的初始化,依赖注入往往是在这里进行的,这个exposedObject在初始化完成之后会作为依赖注入完成之后的Bean 53 // Initialize the bean instance. 54 Object exposedObject = bean; 55 try { 56 //属性的填充 57 populateBean(beanName, mbd, instanceWrapper); 58 if (exposedObject != null) { 59 exposedObject = initializeBean(beanName, exposedObject, mbd); 60 } 61 } 62 catch (Throwable ex) { 63 if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { 64 throw (BeanCreationException) ex; 65 } 66 else { 67 throw new BeanCreationException( 68 mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); 69 } 70 } 71 72 if (earlySingletonExposure) { 73 Object earlySingletonReference = getSingleton(beanName, false); 74 if (earlySingletonReference != null) { 75 if (exposedObject == bean) { 76 exposedObject = earlySingletonReference; 77 } 78 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { 79 String[] dependentBeans = getDependentBeans(beanName); 80 Set
actualDependentBeans = new LinkedHashSet
(dependentBeans.length); 81 for (String dependentBean : dependentBeans) { 82 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { 83 actualDependentBeans.add(dependentBean); 84 } 85 } 86 if (!actualDependentBeans.isEmpty()) { 87 throw new BeanCurrentlyInCreationException(beanName, 88 "Bean with name '" + beanName + "' has been injected into other beans [" + 89 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + 90 "] in its raw version as part of a circular reference, but has eventually been " + 91 "wrapped. This means that said other beans do not use the final version of the " + 92 "bean. This is often the result of over-eager type matching - consider using " + 93 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); 94 } 95 } 96 } 97 } 98 99 // Register bean as disposable.100 try {101 registerDisposableBeanIfNecessary(beanName, bean, mbd);102 }103 catch (BeanDefinitionValidationException ex) {104 throw new BeanCreationException(105 mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);106 }107 108 return exposedObject;109 }

  这里要说一下,当在创建bean时,IOC会将该bean的名字存一份到singletonsCurrentlyInCreation这个map中,然后每次创建的时候都会到里面进行检查当前bean是否正在被创建。为了避免发生循环引用(A依赖B,B依赖C,C依赖A)引起是循环,在第一次创建bean时,IOC容器会把用于创建这个bean的工厂对象放入singletonFactories这个map中,key是这个正在被创建的bean的名字。这样发生循环依赖的时候,就不再调用getBean方法了,而是直接使用工厂创建一个bean给被依赖的对象。比如第一次创建A时,将A的名称存入了singletonsCurrentlyInCreation这个map中,并且调用addSingletonFactory方法,将创建A的工厂放到singletonFactories中了,然后递归调用getBean创建依赖对象B、C,创建C时,要先创建它的依赖对象A,此时,IOC容器检查到singletonsCurrentlyInCreation中已经有这个A了,说明它已经在创建的过程中,只是还没有完成创建,此时,IOC容器直接就使用这个工厂将A创建出来赋给C了,然后再往回完成B和A的创建。可以看一下addSingletonFactory方法的实现:

1 protected void addSingletonFactory(String beanName, ObjectFactory
singletonFactory) { 2 Assert.notNull(singletonFactory, "Singleton factory must not be null"); 3 synchronized (this.singletonObjects) { 4 if (!this.singletonObjects.containsKey(beanName)) { 5 this.singletonFactories.put(beanName, singletonFactory); 6 this.earlySingletonObjects.remove(beanName); 7 this.registeredSingletons.add(beanName); 8 } 9 }10 }
1 public Object getSingleton(String beanName) {2         return getSingleton(beanName, true);3     }
1 protected Object getSingleton(String beanName, boolean allowEarlyReference) { 2         //从缓存中获取该bean的实例,已经填充了属性值的实例 3         Object singletonObject = this.singletonObjects.get(beanName); 4         //创建bean时,IOC会在this.singletonsCurrentlyInCreation中存一个该bean的名称,表示正在创建这个bean 5         if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { 6             synchronized (this.singletonObjects) { 7                 //也是从缓存中获取实例,但是这个缓存中的实例是没有经过填充的实例 8                 singletonObject = this.earlySingletonObjects.get(beanName); 9                 if (singletonObject == null && allowEarlyReference) {10                     //获取生成该bean的beanFactory11                     ObjectFactory
singletonFactory = this.singletonFactories.get(beanName);12 if (singletonFactory != null) {13 //获取这个bean的实例14 singletonObject = singletonFactory.getObject();15 //将这个还未经填充属性的bean存入新生代缓存中(自己取的名字,类似于JVM)16 this.earlySingletonObjects.put(beanName, singletonObject);17 //将这个生产bean的工厂移除18 this.singletonFactories.remove(beanName);19 }20 }21 }22 }23 return (singletonObject != NULL_OBJECT ? singletonObject : null);24 }

  在进行递归调用getBean方法创建依赖对象之前,getSignal方法是先调用的,前面的代码,doGetBean方法中可以看到,可以多看几遍就能理解。另外,对于原型实例,不允许循环引用。循环引用只针对单例。下一篇跟踪bean的属性的填充。

转载于:https://www.cnblogs.com/helei123/p/11087463.html

你可能感兴趣的文章
Microsoft 365及应用开发的未来:微软BUILD 2018大会第二天主题演讲
查看>>
白话中台战略:中台是个什么鬼?
查看>>
Java值类型设计进展
查看>>
《Spark大数据分析》一书的书评和采访
查看>>
The Agile Mind-Set作者访谈
查看>>
Mads Torgersen介绍C# 7及后续版本新特性
查看>>
高通与华为短暂和解,理智看待国内5G现状
查看>>
Gartner调查:AI将成为企业颠覆的重要力量
查看>>
爱立信电信软件的持续交付
查看>>
微软必应从.NET Core 2.1获得了性能提升
查看>>
DevOps实战:Graphite监控上手指南
查看>>
SSPL的MongoDB再被抛弃,GUN Health也合流PostgreSQL
查看>>
知乎pure render专栏创办人@流形:选择React这条路,很庆幸
查看>>
修复.NET的HttpClient
查看>>
调查:Android的领先地位稳固
查看>>
在Maven项目中使用JUnit进行单元测试
查看>>
Docker发布应用程序指南
查看>>
你朋友圈里的广告是怎么做到合你胃口的?
查看>>
#第1天#《C Primer Plus》学习历程
查看>>
为什么说GraphQL可以取代REST API?
查看>>