spring原始碼解析之IOC容器(三)——依賴注入
上一篇主要是跟蹤了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> T getBean(String name, Class<T> 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> T getBean(Class<T> requiredType) throws BeansException { return getBean(requiredType, (Object[]) null); }
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException { NamedBeanHolder<T> 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> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException { 2 return doGetBean(name, requiredType, args, false); 3 }
裡面都呼叫了doGetBean方法,那麼進入繼續跟蹤:
1 protected <T> T doGetBean( 2 final String name, final Class<T> 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<Object>() { 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<Object>() { 128 @Override 129 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<Object>() { 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<String> actualDependentBeans = new LinkedHashSet<String>(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的beanFactory 11 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的屬性的填