SpringBoot系列文章簡介
SpringBoot源碼閱讀輔助篇:
SpringBoot啟動流程源碼分析:
- SpringBoot啟動流程分析(一):SpringApplication類初始化過程
- SpringBoot啟動流程分析(二):SpringApplication的run方法
- SpringBoot啟動流程分析(三):SpringApplication的run方法之prepareContext()方法
- SpringBoot啟動流程分析(四):IoC容器的初始化過程
- SpringBoot啟動流程分析(五):SpringBoot自動裝配原理實現
- SpringBoot啟動流程分析(六):IoC容器依賴注入
筆者注釋版Spring Framework與SpringBoot源碼git傳送門:請不要吝嗇小星星
一、前言
前面我們對IoC容器的初始化過程進行了詳細的分析,這個初始化過程完成的主要工作是在IoC容器中建立BeanDefinition數據映射。在此過程中並沒有看到IoC容器對Bean依賴關系進行注入,接下來分析一下IoC容器是怎樣對Bean的依賴關系進行注入的。
前面在refresh()-->invokeBeanFactoryPostProcessors(beanFactory);方法中已經完成了IoC容器的初始化並已經載入了我們定義的Bean的信息(BeanDefinition),現在我們開始分析依賴注入的原理。首先需要說明的是依賴注入在用戶第一次向IoC容器索要Bean時觸發,當然也有例外,我們可以在BeanDefinition中中通過控制lazy-init屬性來讓容器完成對Bean的預實例化。這個預實例化實際上也是一個依賴注入的過程,但它是在初始化過程中完成的。
二、源碼分析
2.1、getBean()的過程
接着前面看refresh()方法,這已經是refresh()方法的第三篇博文了,別迷糊我們還沒走出refresh()方法。
1 // AbstractApplicationContext類 2 @Override 3 public void refresh() throws BeansException, IllegalStateException { 4 synchronized (this.startupShutdownMonitor) { 5 ... 6 try { 7 ... 8 // Instantiate all remaining (non-lazy-init) singletons. 9 finishBeanFactoryInitialization(beanFactory); 10 ... 11 } 12 ... 13 } 14 } 15 // AbstractApplicationContext類 16 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { 17 ... 18 // Instantiate all remaining (non-lazy-init) singletons. 19 // 實例化所有剩余的(non-lazy-init)單例。 20 beanFactory.preInstantiateSingletons(); 21 } 22 // DefaultListableBeanFactory類 23 @Override 24 public void preInstantiateSingletons() throws BeansException { 25 ... 26 // Iterate over a copy to allow for init methods which in turn register new bean definitions. 27 // While this may not be part of the regular factory bootstrap, it does otherwise work fine. 28 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); 29 // Trigger initialization of all non-lazy singleton beans... 30 for (String beanName : beanNames) { 31 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); 32 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { 33 if (isFactoryBean(beanName)) { 34 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); 35 if (bean instanceof FactoryBean) { 36 final FactoryBean<?> factory = (FactoryBean<?>) bean; 37 boolean isEagerInit; 38 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { 39 isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) 40 ((SmartFactoryBean<?>) factory)::isEagerInit, 41 getAccessControlContext()); 42 } else { 43 isEagerInit = (factory instanceof SmartFactoryBean && 44 ((SmartFactoryBean<?>) factory).isEagerInit()); 45 } 46 if (isEagerInit) { 47 getBean(beanName); 48 } 49 } 50 } else { 51 // 這里就是觸發依賴注入的地方 52 getBean(beanName); 53 } 54 } 55 } 56 ... 57 }
跟蹤其調用棧,看到上面第52行的getBean(beanName);方法,我們再梳理一下getBean()方法,前面總結過該方法在IoC容器的頂層接口BeanFactory中定義,然后在IoC容器的具體產品DefaultListableBeanFactory類的基類AbstractBeanFactory實現了getBean()方法。接着看代碼。
1 // AbstractBeanFactory類 2 @Override 3 public Object getBean(String name) throws BeansException { 4 return doGetBean(name, null, null, false); 5 } 6 @Override 7 public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException { 8 return doGetBean(name, requiredType, null, false); 9 } 10 @Override 11 public Object getBean(String name, Object... args) throws BeansException { 12 return doGetBean(name, null, args, false); 13 } 14 public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) 15 throws BeansException { 16 return doGetBean(name, requiredType, args, false); 17 }
從上面代碼可知大致可分為兩種獲取Bean的參數,一種是按名獲取,一種是按類獲取。但是最終都進入到了doGetBean()方法。
1 // AbstractBeanFactory類 2 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, 3 @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { 4 5 // bean獲取過程:先獲取bean名字 6 // 會把帶有&前綴的去掉,或者去aliasMap中找這個是不是別名,最終確定bean的id是什么 7 final String beanName = transformedBeanName(name); 8 Object bean; 9 10 // 1.檢查緩存中或者實例工廠中是否有對應的實例 11 // 因為在創建單例bean的時候會存在依賴注入的情況,而在創建依賴的時候為了避免循環依賴 12 // Spring在創建bean的時候不會等bean創建完成就會將bean的ObjectFactory提早曝光 13 // 也就是將ObjectFactory加入到緩存中,一旦下一個要創建的bean需要依賴上個bean則直接使用ObjectFactory 14 // 2.spring 默認是單例的,如果能獲取到直接返回,提高效率。 15 // Eagerly check singleton cache for manually registered singletons. 16 Object sharedInstance = getSingleton(beanName); 17 if (sharedInstance != null && args == null) { 18 if (logger.isDebugEnabled()) { 19 if (isSingletonCurrentlyInCreation(beanName)) { 20 logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + 21 "' that is not fully initialized yet - a consequence of a circular reference"); 22 } 23 else { 24 logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); 25 } 26 } 27 // 用於檢測bean的正確性,同時如果獲取的是FactoryBean的話還需要調用getObject()方法獲取最終的那個bean實例 28 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 29 } 30 31 else { 32 // Fail if we're already creating this bean instance: 33 // We're assumably within a circular reference. 34 if (isPrototypeCurrentlyInCreation(beanName)) { 35 throw new BeanCurrentlyInCreationException(beanName); 36 } 37 38 // Check if bean definition exists in this factory. 39 //這里對IoC容器中的BeanDefinition是否存在進行檢查,檢查是否能在當前的BeanFactory中取得需要的Bean。 40 // 如果當前的工廠中取不到,則到雙親BeanFactory中去取。如果當前的雙親工廠取不到,那就順着雙親BeanFactory 41 // 鏈一直向上查找。 42 BeanFactory parentBeanFactory = getParentBeanFactory(); 43 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 44 // Not found -> check parent. 45 String nameToLookup = originalBeanName(name); 46 if (parentBeanFactory instanceof AbstractBeanFactory) { 47 // 遞歸調用父bean的doGetBean查找 48 return ((AbstractBeanFactory) parentBeanFactory).doGetBean( 49 nameToLookup, requiredType, args, typeCheckOnly); 50 } 51 else if (args != null) { 52 // Delegation to parent with explicit args. 53 return (T) parentBeanFactory.getBean(nameToLookup, args); 54 } 55 else { 56 // No args -> delegate to standard getBean method. 57 return parentBeanFactory.getBean(nameToLookup, requiredType); 58 } 59 } 60 61 if (!typeCheckOnly) { 62 markBeanAsCreated(beanName); 63 } 64 65 try { 66 //這里根據Bean的名字取得BeanDefinition 67 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 68 checkMergedBeanDefinition(mbd, beanName, args); 69 70 // Guarantee initialization of beans that the current bean depends on. 71 //獲取當前Bean的所有依賴Bean,這里會觸發getBean的遞歸調用。知道取到一個沒有任何依賴的Bean為止。 72 String[] dependsOn = mbd.getDependsOn(); 73 if (dependsOn != null) { 74 for (String dep : dependsOn) { 75 if (isDependent(beanName, dep)) { 76 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 77 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); 78 } 79 registerDependentBean(dep, beanName); 80 try { 81 getBean(dep); 82 } 83 catch (NoSuchBeanDefinitionException ex) { 84 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 85 "'" + beanName + "' depends on missing bean '" + dep + "'", ex); 86 } 87 } 88 } 89 90 // 這里通過createBean方法創建singleton Bean的實例 這里還有一個回調函數 91 // Create bean instance. 92 if (mbd.isSingleton()) { 93 sharedInstance = getSingleton(beanName, () -> { 94 try { 95 // 最后在getSingleton中又會調用這個方法 96 // TODO createBean的入口 97 return createBean(beanName, mbd, args); 98 } 99 catch (BeansException ex) { 100 // Explicitly remove instance from singleton cache: It might have been put there 101 // eagerly by the creation process, to allow for circular reference resolution. 102 // Also remove any beans that received a temporary reference to the bean. 103 destroySingleton(beanName); 104 throw ex; 105 } 106 }); 107 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 108 } 109 // 這里是創建prototype bean的地方 110 else if (mbd.isPrototype()) { 111 // It's a prototype -> create a new instance. 112 Object prototypeInstance = null; 113 try { 114 beforePrototypeCreation(beanName); 115 prototypeInstance = createBean(beanName, mbd, args); 116 } 117 finally { 118 afterPrototypeCreation(beanName); 119 } 120 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); 121 } 122 123 else { 124 String scopeName = mbd.getScope(); 125 final Scope scope = this.scopes.get(scopeName); 126 if (scope == null) { 127 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); 128 } 129 try { 130 Object scopedInstance = scope.get(beanName, () -> { 131 beforePrototypeCreation(beanName); 132 try { 133 return createBean(beanName, mbd, args); 134 } 135 finally { 136 afterPrototypeCreation(beanName); 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 //這里對創建的Bean進行類型檢查,如果沒有問題,就返回這個新創建的Bean,這個Bean已經是包含了依賴關系的Bean 157 if (requiredType != null && !requiredType.isInstance(bean)) { 158 try { 159 T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); 160 if (convertedBean == null) { 161 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); 162 } 163 return convertedBean; 164 } 165 catch (TypeMismatchException ex) { 166 if (logger.isDebugEnabled()) { 167 logger.debug("Failed to convert bean '" + name + "' to required type '" + 168 ClassUtils.getQualifiedName(requiredType) + "'", ex); 169 } 170 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); 171 } 172 } 173 return (T) bean; 174 }
這個就是依賴注入的入口了,依賴注入是在容器的BeanDefinition數據已經建立好的前提下進行的。“程序=數據+算法”,很經典的一句話,前面我們詳細介紹了BeanDefinition的注冊過程,BeanDefinition就是數據。如上面代碼所示,doGetBean()方法不涉及復雜的算法,但是這個過程也不是很簡單,因為我們都知道,對於IoC容器的使用,Spring提供了很多的配置參數,每一個配置參數實際上就代表了一個IoC容器的實現特征,這些特征很多都需要在依賴注入的過程或者對Bean進行生命周期管理的過程中完成。雖然我們可以簡單的將IoC容器描述成一個ConcurrentHashMap,ConcurrentHashMap只是它的數據結構而不是IoC容器的全部。
TIPS: 1,我在工程中簡單寫了一個controller和一個service,我們在后面debug看看依賴注入的過程是怎么樣的, 也不知道我能不能說清楚。希望大家看到這一塊多debug一下,debug技巧如下圖所示,寫了debug的條件, 因為這邊到處都是遞歸和回調函數,再加上有很多Spring的Bean,但是我們只關心自己的Bean, 所以就寫了這樣的過濾條件:beanName.equals("webController")||beanName.equals("webService") @RestController public class WebController { @Autowired private WebService webService; @RequestMapping("/web") public String web(){ return webService.hello(); } }

下面我們通過代碼看看獲取bean的過程。
OK,看代碼,Object sharedInstance = getSingleton(beanName);如注釋所說,首先回去找在容器中是不是已經存在該單例。具體在哪找我們在前面的文章中已經說得很清楚了。看一下getSingleton()方法
1 // DefaultSingletonBeanRegistry類 2 protected Object getSingleton(String beanName, boolean allowEarlyReference) { 3 // 由於scope是singleton,所以先從緩存中取單例對象的實例,如果取到直接返回,沒有取到加載bean 4 Object singletonObject = this.singletonObjects.get(beanName); 5 // 當想要獲取的bean沒有被加載,並且也沒有正在被創建的時候,主動去加載bean 6 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { 7 // 鎖住單例緩存區加載bean 8 synchronized (this.singletonObjects) { 9 // singletonObjects ,earlySingletonObjects ,singletonFactories是一個單例實例的三種存在狀態 10 // 再去earlySingletonObjects中去找 11 singletonObject = this.earlySingletonObjects.get(beanName); 12 if (singletonObject == null && allowEarlyReference) { 13 // 去singletonFactories中去找對象的實例 14 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); 15 if (singletonFactory != null) { 16 singletonObject = singletonFactory.getObject(); 17 this.earlySingletonObjects.put(beanName, singletonObject); 18 this.singletonFactories.remove(beanName); 19 } 20 } 21 } 22 } 23 return singletonObject; 24 }
在DefaultSingletonBeanRegistry類中的singletonObjects屬性就是存singleton bean的地方。
如果getSingleton()為 null繼續往下看,會在當前的BeanFactory中獲取BeanDefinition,也就是這行方法代碼:final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);在這行代碼拿到BeanDefinition后,首先判斷是不是singleton Bean,如果是的話,開始執行創建Bean,正是return createBean(beanName, mbd, args);這行代碼。如果是原型(Prototype)Bean我們就不分析了。原型bean每次執行getBean()都會創建一個實例。接下來我們看createBean()方法。
2.2、createBean()的過程
首先看一下create bean的過程
1,Bean實例的創建 2,為Bean實例設置屬性(屬性注入,其實就是依賴注入真正發生的地方) 3,調用Bean的初始化方法
前面說了getBean()是依賴注入的起點,之后會調用createBean(),下面通過createBean()代碼來了解這個過程。在這個過程中,Bean對象會根據BeanDefinition定義的要求生成。
1 // AbstractAutowireCapableBeanFactory類 2 @Override 3 protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 4 throws BeanCreationException { 5 ... 6 try { 7 // 驗證以及准備override的方法 8 mbdToUse.prepareMethodOverrides(); 9 } 10 catch (BeanDefinitionValidationException ex) { 11 throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), 12 beanName, "Validation of method overrides failed", ex); 13 } 14 try { 15 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. 16 // createBean之前調用BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法 17 // 默認不做任何處理所以會返回null 18 // 但是如果我們重寫了這兩個方法,那么bean的創建過程就結束了,這里就為以后的annotation自動注入提供了鈎子 19 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); 20 if (bean != null) { 21 return bean; 22 } 23 }catch (Throwable ex) { 24 throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, 25 "BeanPostProcessor before instantiation of bean failed", ex); 26 } 27 try { 28 // 實際執行createBean的是doCreateBean()方法 29 Object beanInstance = doCreateBean(beanName, mbdToUse, args); 30 if (logger.isDebugEnabled()) { 31 logger.debug("Finished creating instance of bean '" + beanName + "'"); 32 } 33 return beanInstance; 34 } 35 catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { 36 // A previously detected exception with proper bean creation context already, 37 // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. 38 throw ex; 39 } 40 catch (Throwable ex) { 41 throw new BeanCreationException( 42 mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); 43 } 44 }
接着往下看doCreateBean()方法。
1 // AbstractAutowireCapableBeanFactory類 2 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) 3 throws BeanCreationException { 4 // BeanWrapper是用來持有創建出來的Bean對象 5 // Instantiate the bean. 6 BeanWrapper instanceWrapper = null; 7 // 如果是單例,先把緩存中的同名Bean清除 8 if (mbd.isSingleton()) { 9 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 10 } 11 // 這里是創建Bean的地方,由createBeanInstance完成。 12 // TODO 完成Bean初始化過程的第一步:創建實例 13 if (instanceWrapper == null) { 14 instanceWrapper = createBeanInstance(beanName, mbd, args); 15 } 16 final Object bean = instanceWrapper.getWrappedInstance(); 17 Class<?> beanType = instanceWrapper.getWrappedClass(); 18 if (beanType != NullBean.class) { 19 mbd.resolvedTargetType = beanType; 20 } 21 22 // Allow post-processors to modify the merged bean definition. 23 synchronized (mbd.postProcessingLock) { 24 if (!mbd.postProcessed) { 25 try { 26 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 27 } 28 catch (Throwable ex) { 29 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 30 "Post-processing of merged bean definition failed", ex); 31 } 32 mbd.postProcessed = true; 33 } 34 } 35 36 // Eagerly cache singletons to be able to resolve circular references 37 // even when triggered by lifecycle interfaces like BeanFactoryAware. 38 // 是否自動解決循環引用 39 // 當bean條件為: 單例&&允許循環引用&&正在創建中這樣的話提早暴露一個ObjectFactory 40 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && 41 isSingletonCurrentlyInCreation(beanName)); 42 if (earlySingletonExposure) { 43 if (logger.isDebugEnabled()) { 44 logger.debug("Eagerly caching bean '" + beanName + 45 "' to allow for resolving potential circular references"); 46 } 47 // 把ObjectFactory放進singletonFactories中 48 // 這里在其他bean在創建的時候會先去singletonFactories中查找有沒有beanName到ObjectFactory的映射 49 // 如果有ObjectFactory就調用它的getObject方法獲取實例 50 // 但是在這里就可以對一個bean進行保證,代理等等AOP就可以在getEarlyBeanReference這里實現 51 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 52 } 53 54 // Initialize the bean instance. 55 Object exposedObject = bean; 56 try { 57 // TODO 完成Bean初始化過程的第二步:為Bean的實例設置屬性 58 // Bean依賴注入發生的地方 59 // 對bean進行屬性填充,如果存在依賴於其他的bean的屬性,則會遞歸的調用初始化依賴的bean 60 populateBean(beanName, mbd, instanceWrapper); 61 // TODO 完成Bean初始化過程的第三步:調用Bean的初始化方法(init-method) 62 // 調用初始化方法,比如init-method方法指定的方法 63 exposedObject = initializeBean(beanName, exposedObject, mbd); 64 } 65 catch (Throwable ex) { 66 if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { 67 throw (BeanCreationException) ex; 68 } 69 else { 70 throw new BeanCreationException( 71 mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); 72 } 73 } 74 75 if (earlySingletonExposure) { 76 Object earlySingletonReference = getSingleton(beanName, false); 77 if (earlySingletonReference != null) { 78 if (exposedObject == bean) { 79 exposedObject = earlySingletonReference; 80 } 81 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { 82 String[] dependentBeans = getDependentBeans(beanName); 83 Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); 84 for (String dependentBean : dependentBeans) { 85 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { 86 actualDependentBeans.add(dependentBean); 87 } 88 } 89 if (!actualDependentBeans.isEmpty()) { 90 throw new BeanCurrentlyInCreationException(beanName, 91 "Bean with name '" + beanName + "' has been injected into other beans [" + 92 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + 93 "] in its raw version as part of a circular reference, but has eventually been " + 94 "wrapped. This means that said other beans do not use the final version of the " + 95 "bean. This is often the result of over-eager type matching - consider using " + 96 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); 97 } 98 } 99 } 100 } 101 102 // Register bean as disposable. 103 try { 104 // 注冊銷毀方法,比如:可以在配置bean的時候指定destory-method方法 105 registerDisposableBeanIfNecessary(beanName, bean, mbd); 106 } 107 catch (BeanDefinitionValidationException ex) { 108 throw new BeanCreationException( 109 mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); 110 } 111 112 return exposedObject; 113 }
結合上面的代碼,我們再來看一下創建Bean的三個步驟,是不是有點豁然開朗的感覺。別着急繼續往下看。
1,Bean實例的創建,instanceWrapper = createBeanInstance(beanName, mbd, args); 2,為Bean實例設置屬性,populateBean(beanName, mbd, instanceWrapper); 3,調用Bean的初始化方法,exposedObject = initializeBean(beanName, exposedObject, mbd);
2.2.1、createBeanInstance():Bean實例的創建
看代碼
1 // AbstractAutowireCapableBeanFactory類 2 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { 3 // Make sure bean class is actually resolved at this point. 4 // 確認需要創建的Bean的實例的類可以實例化 5 Class<?> beanClass = resolveBeanClass(mbd, beanName); 6 7 if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { 8 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 9 "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); 10 } 11 12 Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); 13 if (instanceSupplier != null) { 14 return obtainFromSupplier(instanceSupplier, beanName); 15 } 16 17 // 當有工廠方法的時候使用工廠方法初始化Bean,就是配置的時候指定FactoryMethod屬性,類似注解中的@Bean把方法的返回值作為Bean 18 if (mbd.getFactoryMethodName() != null) { 19 return instantiateUsingFactoryMethod(beanName, mbd, args); 20 } 21 22 // Shortcut when re-creating the same bean... 23 boolean resolved = false; 24 boolean autowireNecessary = false; 25 if (args == null) { 26 synchronized (mbd.constructorArgumentLock) { 27 if (mbd.resolvedConstructorOrFactoryMethod != null) { 28 resolved = true; 29 autowireNecessary = mbd.constructorArgumentsResolved; 30 } 31 } 32 } 33 if (resolved) { 34 if (autowireNecessary) { 35 // 如果有有參數的構造函數,構造函數自動注入 36 // 這里spring會花費大量的精力去進行參數的匹配 37 return autowireConstructor(beanName, mbd, null, null); 38 } 39 else { 40 // 如果沒有有參構造函數,使用默認構造函數構造 41 return instantiateBean(beanName, mbd); 42 } 43 } 44 45 // Need to determine the constructor... 46 // 使用構造函數進行實例化 47 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); 48 if (ctors != null || 49 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || 50 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { 51 return autowireConstructor(beanName, mbd, ctors, args); 52 } 53 54 // No special handling: simply use no-arg constructor. 55 // 使用默認的構造函數對Bean進行實例化 56 return instantiateBean(beanName, mbd); 57 }
我們可以看到在instantiateBean()方法中生成了Bean所包含的Java對象,這個對象的生成有很多種不同的方式,可以通過工廠方法生成,也可以通過容器的autowire特性生成,這些生成方式都是由BeanDefinition決定的。對於上面我們的WebController和WebService兩個類是通過最后一行,使用默認的構造函數進行Bean的實例化。
接着看instantiateBean()方法。
1 // AbstractAutowireCapableBeanFactory類 2 protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { 3 // 使用默認的實例化策略對Bean進行實例化,默認的實例化策略是CglibSubclassingInstantiationStrategy, 4 // 也就是常說的CGLIB來對Bean進行實例化。PS:面試官常問的字節碼增強 5 try { 6 Object beanInstance; 7 final BeanFactory parent = this; 8 if (System.getSecurityManager() != null) { 9 beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> 10 getInstantiationStrategy().instantiate(mbd, beanName, parent), 11 getAccessControlContext()); 12 } 13 else { 14 // getInstantiationStrategy()會返回CglibSubclassingInstantiationStrategy類的實例 15 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); 16 } 17 BeanWrapper bw = new BeanWrapperImpl(beanInstance); 18 initBeanWrapper(bw); 19 return bw; 20 } 21 catch (Throwable ex) { 22 throw new BeanCreationException( 23 mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); 24 } 25 }
這里使用CGLIB進行Bean的實例化。CGLIB是一個常用的字節碼生成器的類庫,其提供了一系列的API來提供生成和轉換Java字節碼的功能。在Spring AOP中同樣也是使用的CGLIB對Java的字節碼進行增強。在IoC容器中,使用SimpleInstantiationStrategy類。這個類是Spring用來生成Bean對象的默認類,它提供了兩種實例化Java對象的方法,一種是通過BeanUtils,它使用的是JVM的反射功能,一種是通過CGLIB來生成。
getInstantiationStrategy()方法獲取到CglibSubclassingInstantiationStrategy實例,instantiate()是CglibSubclassingInstantiationStrategy類的父類SimpleInstantiationStrategy實現的。
繼續看代碼
1 // SimpleInstantiationStrategy類 2 @Override 3 public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { 4 // Don't override the class with CGLIB if no overrides. 5 // 如果BeanFactory重寫了Bean內的方法,則使用CGLIB,否則使用BeanUtils 6 if (!bd.hasMethodOverrides()) { 7 // 如果bean沒有需要動態替換的方法就直接反射進行創建實例 8 Constructor<?> constructorToUse; 9 synchronized (bd.constructorArgumentLock) { 10 constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; 11 if (constructorToUse == null) { 12 final Class<?> clazz = bd.getBeanClass(); 13 if (clazz.isInterface()) { 14 throw new BeanInstantiationException(clazz, "Specified class is an interface"); 15 } 16 try { 17 if (System.getSecurityManager() != null) { 18 constructorToUse = AccessController.doPrivileged( 19 (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor); 20 } else { 21 constructorToUse = clazz.getDeclaredConstructor(); 22 } 23 bd.resolvedConstructorOrFactoryMethod = constructorToUse; 24 } catch (Throwable ex) { 25 throw new BeanInstantiationException(clazz, "No default constructor found", ex); 26 } 27 } 28 } 29 // 通過BeanUtils進行實例化,這個BeanUtils的實例化通過Constructor類實例化Bean 30 // 在BeanUtils中可以看到具體的調用ctor.newInstances(args) 31 return BeanUtils.instantiateClass(constructorToUse); 32 } else { 33 // Must generate CGLIB subclass. 34 // TODO 使用CGLIB實例化對象 35 return instantiateWithMethodInjection(bd, beanName, owner); 36 } 37 }
在SpringBoot中我們一般采用@Autowire的方式進行依賴注入,很少采用像SpringMVC那種在xml中使用<lookup-method>或者<replaced-method>等標簽的方式對注入的屬性進行override,所以在上面的代碼中if(!bd.hasMethodOverrides())中的判斷為true,會采用BeanUtils的實例化方式。
2.2.2、populateBean();屬性設置(依賴注入)
看代碼
1 protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { 2 if (bw == null) { 3 if (mbd.hasPropertyValues()) { 4 throw new BeanCreationException( 5 mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); 6 } 7 else { 8 // Skip property population phase for null instance. 9 return; 10 } 11 } 12 // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the 13 // state of the bean before properties are set. This can be used, for example, 14 // to support styles of field injection. 15 boolean continueWithPropertyPopulation = true; 16 // 調用InstantiationAwareBeanPostProcessor Bean的后置處理器,在Bean注入屬性前改變BeanDefinition的信息 17 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { 18 for (BeanPostProcessor bp : getBeanPostProcessors()) { 19 if (bp instanceof InstantiationAwareBeanPostProcessor) { 20 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 21 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { 22 continueWithPropertyPopulation = false; 23 break; 24 } 25 } 26 } 27 } 28 if (!continueWithPropertyPopulation) { 29 return; 30 } 31 // 這里取得在BeanDefinition中設置的property值,這些property來自對BeanDefinition的解析 32 // 用於在配置文件中通過<property>配置的屬性並且顯示在配置文件中配置了autowireMode屬性 33 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); 34 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || 35 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { 36 MutablePropertyValues newPvs = new MutablePropertyValues(pvs); 37 38 // Add property values based on autowire by name if applicable. 39 // 這里對autowire注入的處理,autowire by name 40 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { 41 autowireByName(beanName, mbd, bw, newPvs); 42 } 43 44 // Add property values based on autowire by type if applicable. 45 // 這里對autowire注入的處理, autowire by type 46 // private List<Test> tests; 47 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { 48 autowireByType(beanName, mbd, bw, newPvs); 49 } 50 51 pvs = newPvs; 52 } 53 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); 54 boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); 55 if (hasInstAwareBpps || needsDepCheck) { 56 if (pvs == null) { 57 pvs = mbd.getPropertyValues(); 58 } 59 PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); 60 if (hasInstAwareBpps) { 61 for (BeanPostProcessor bp : getBeanPostProcessors()) { 62 if (bp instanceof InstantiationAwareBeanPostProcessor) { 63 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 64 // TODO @Autowire @Resource @Value @Inject 等注解的依賴注入過程 65 pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); 66 if (pvs == null) { 67 return; 68 } 69 } 70 } 71 } 72 if (needsDepCheck) { 73 checkDependencies(beanName, mbd, filteredPds, pvs); 74 } 75 } 76 if (pvs != null) { 77 // 注入配置文件中<property>配置的屬性 78 applyPropertyValues(beanName, mbd, bw, pvs); 79 } 80 }
上面方法中的31-52行以及78行的applyPropertyValues()方法基本都是用於SpringMVC中采用xml配置Bean的方法。所以我們不做介紹了。看注釋知道干嘛的就行了。我們主要看的是pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);這行代碼,這行代碼是真正執行采用@Autowire @Resource @Value @Inject 等注解的依賴注入過程。
接着往下看
1 // AutowiredAnnotationBeanPostProcessor類 2 @Override 3 public PropertyValues postProcessPropertyValues( 4 PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { 5 // 遍歷,獲取@Autowire,@Resource,@Value,@Inject等具備注入功能的注解 6 InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); 7 try { 8 // 屬性注入 9 metadata.inject(bean, beanName, pvs); 10 } catch (BeanCreationException ex) { 11 throw ex; 12 } catch (Throwable ex) { 13 throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex); 14 } 15 return pvs; 16 }
AutowiredAnnotationBeanPostProcessor類實現了postProcessPropertyValues()方法。findAutowiringMetadata(beanName, bean.getClass(), pvs);方法會尋找在當前類中的被@Autowire,@Resource,@Value,@Inject等具備注入功能的注解的屬性。
debug看一下結果,如下圖所示,成功得到了@Autowire注解的屬性webService。
metadata.inject(bean, beanName, pvs);方法開始執行注入的邏輯。
1 // AutowiredAnnotationBeanPostProcessor類 2 @Override 3 protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { 4 // 需要注入的字段 5 Field field = (Field) this.member; 6 // 需要注入的屬性值 7 Object value; 8 if (this.cached) { 9 value = resolvedCachedArgument(beanName, this.cachedFieldValue); 10 } else { 11 // @Autowired(required = false),當在該注解中設置為false的時候,如果有直接注入,沒有跳過,不會報錯。 12 DependencyDescriptor desc = new DependencyDescriptor(field, this.required); 13 desc.setContainingClass(bean.getClass()); 14 Set<String> autowiredBeanNames = new LinkedHashSet<>(1); 15 Assert.state(beanFactory != null, "No BeanFactory available"); 16 TypeConverter typeConverter = beanFactory.getTypeConverter(); 17 try { 18 // 通過BeanFactory 解決依賴關系 19 // 比如在webController中注入了webService,這個會去BeanFactory中去獲取webService,也就是getBean()的邏輯。 20 // 如果存在直接返回,不存在再執行createBean()邏輯。 21 // 如果在webService中依然依賴,依然會去遞歸。 22 // 這里是一個復雜的遞歸邏輯。 23 value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); 24 } catch (BeansException ex) { 25 throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); 26 } 27 synchronized (this) { 28 if (!this.cached) { 29 if (value != null || this.required) { 30 this.cachedFieldValue = desc; 31 registerDependentBeans(beanName, autowiredBeanNames); 32 if (autowiredBeanNames.size() == 1) { 33 String autowiredBeanName = autowiredBeanNames.iterator().next(); 34 if (beanFactory.containsBean(autowiredBeanName) && 35 beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { 36 this.cachedFieldValue = new ShortcutDependencyDescriptor( 37 desc, autowiredBeanName, field.getType()); 38 } 39 } 40 } else { 41 this.cachedFieldValue = null; 42 } 43 this.cached = true; 44 } 45 } 46 } 47 if (value != null) { 48 ReflectionUtils.makeAccessible(field); 49 field.set(bean, value); 50 } 51 }
debug看一下field。如下圖所示正是我們的webService
看這行代碼:value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);注意beanFactory依舊是我們熟悉的IoC容器的具體產品,也就是實現類DefaultListableBeanFactory。見到就說一遍,方便大家記住它,很重要。
在resolveDependency()方法中經過一頓操作,最終又會來到上面的getBean()方法。以上就是依賴注入的整個過程。注意看代碼中的注釋哦。
2.2.3、initializeBean():調用Bean的初始化方法
設置Bean的初始化方法有兩種方法,一種是在xml或者@Bean指定init-method方法。另一種是讓bean實現InitializingBean接口重寫afterPropertiesSet()方法。
1 // AbstractAutowireCapableBeanFactory類 2 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { 3 if (System.getSecurityManager() != null) { 4 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 5 invokeAwareMethods(beanName, bean); 6 return null; 7 }, getAccessControlContext()); 8 } 9 else { 10 //在調用Bean的初始化方法之前,調用一系列的aware接口實現,把相關的BeanName,BeanClassLoader,以及BeanFactory注入到Bean中去。 11 invokeAwareMethods(beanName, bean); 12 } 13 14 Object wrappedBean = bean; 15 if (mbd == null || !mbd.isSynthetic()) { 16 // 這些都是鈎子方法,在反復的調用,給Spring帶來了極大的可拓展性 17 // 初始化之前調用BeanPostProcessor 18 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 19 } 20 21 try { 22 // 調用指定的init-method方法 23 invokeInitMethods(beanName, wrappedBean, mbd); 24 } 25 catch (Throwable ex) { 26 throw new BeanCreationException( 27 (mbd != null ? mbd.getResourceDescription() : null), 28 beanName, "Invocation of init method failed", ex); 29 } 30 if (mbd == null || !mbd.isSynthetic()) { 31 // 這些都是鈎子方法,在反復的調用,給Spring帶來了極大的可拓展性 32 // 初始化之后調用BeanPostProcessor 33 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 34 } 35 36 return wrappedBean; 37 }
在調用Bean的初始化方法之前,調用一系列的aware接口實現,把相關的BeanName,BeanClassLoader,以及BeanFactory注入到Bean中去。接着會執行invokeInitMethods()方法。
1 // AbstractAutowireCapableBeanFactory類 2 protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) 3 throws Throwable { 4 // 除了使用init-method指定的初始化方法,還可以讓bean實現InitializingBean接口重寫afterPropertiesSet()方法 5 boolean isInitializingBean = (bean instanceof InitializingBean); 6 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { 7 if (logger.isDebugEnabled()) { 8 logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); 9 } 10 if (System.getSecurityManager() != null) { 11 try { 12 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { 13 ((InitializingBean) bean).afterPropertiesSet(); 14 return null; 15 }, getAccessControlContext()); 16 } 17 catch (PrivilegedActionException pae) { 18 throw pae.getException(); 19 } 20 } 21 else { 22 // 執行afterPropertiesSet()方法進行初始化 23 ((InitializingBean) bean).afterPropertiesSet(); 24 } 25 } 26 27 // 先執行afterPropertiesSet()方法,再進行init-method 28 if (mbd != null && bean.getClass() != NullBean.class) { 29 String initMethodName = mbd.getInitMethodName(); 30 if (StringUtils.hasLength(initMethodName) && 31 !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && 32 !mbd.isExternallyManagedInitMethod(initMethodName)) { 33 invokeCustomInitMethod(beanName, bean, mbd); 34 } 35 } 36 }
可見該方法中首先判斷Bean是否配置了init-method方法,如果有,那么通過invokeCustomInitMethod()方法來直接調用。其中在invokeCustomInitMethod()方法中是通過JDK的反射機制得到method對象,然后調用的init-method。最終完成Bean的初始化。
三、總結
SpringBoot啟動流程相關的博文到這里就結束了,在前面的文章中,我們詳細介紹了IoC容器的設計與實現,並結合SpringBoot的啟動流程介紹了IoC容器的初始化過程,及IoC容器的依賴注入,及大家都很關心的SpringBoot是如何實現自動裝配的。關於SpringBoot的源碼分析基本就到這里了,后面有計划寫寫AOP的實現,以及很重要的Spring事務實現。
小半個月時間,熬了很多個凌晨,終於寫完了SpringBoot啟動流程系列博文。有辛苦更有收獲,我是從今年才開始寫博客的,以前每當想寫的時候,總想什么時候能力足夠了,憋個大招再寫。回過頭來看之前的想法是十分錯誤的,寫博文不只是為了分享,最重要的是在寫博客的過程中能夠系統的梳理一下某一個技術棧的知識。好記性不如爛筆頭,看別人的博客很難get到自己想要的點,所以也是讓自己持續進步的一種方式。加油,各位。
原創不易,轉載請注明出處。
如有錯誤的地方還請留言指正。