這一次搞懂Spring的Bean例項化原理操作
前言
前兩篇文章分析了Spring XML和註解的解析原理,並將其封裝為BeanDefinition物件存放到IOC容器中,而這些只是refresh方法中的其中一個步驟——obtainFreshBeanFactory,接下來就將圍繞著這些BeanDefinition物件進行一系列的處理,如BeanDefinitionRegistryPostProcessor物件方法的呼叫、BeanFactoryPostProcessor物件方法的呼叫以及Bean例項的建立都離不開這些BeanDefinition物件。
下面就來看看Spring是如何處理這些物件的。
正文
環境準備
首先我們先回憶下refresh方法:
public void refresh() throws BeansException,IllegalStateException { synchronized (this.startupShutdownMonitor) { //為容器初始化做準備 prepareRefresh(); // 解析xml和註解 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 給BeanFacory設定屬性值以及新增一些處理器,即準備Spring的上下文環境 prepareBeanFactory(beanFactory); try { // 由子類實現對BeanFacoty的一些後置處理 postProcessBeanFactory(beanFactory); /* * BeanDefinitionRegistryPostProcessor * BeanFactoryPostProcessor * 完成對這兩個介面的呼叫 * */ invokeBeanFactoryPostProcessors(beanFactory); /* * 把實現了BeanPostProcessor介面的類例項化,並且加入到BeanFactory中 * */ registerBeanPostProcessors(beanFactory); /* * 國際化 * */ initMessageSource(); //初始化事件管理類 initApplicationEventMulticaster(); //這個方法著重理解模板設計模式,因為在springboot中,這個方法是用來做內嵌tomcat啟動的 onRefresh(); /* * 往事件管理類中註冊事件類 * */ registerListeners(); /* * 1、bean例項化過程 * 2、依賴注入 * 3、註解支援 * 4、BeanPostProcessor的執行 * 5、Aop的入口 * * */ finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } finally { resetCommonCaches(); } } }
prepareBeanFactory和postProcessBeanFactory沒什麼複雜的,關注一下里面設定了哪些值,添加了哪些物件就行,這些東西在後面的流程中會起到作用。
尤其是postProcessBeanFactory,這是一個模板方法,在其子類AbstractRefreshableWebApplicationContext中設定了兩個重要的標識:
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 主要看著裡面 beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext,this.servletConfig)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); beanFactory.ignoreDependencyInterface(ServletConfigAware.class); WebApplicationContextUtils.registerWebApplicationScopes(beanFactory,this.servletContext); WebApplicationContextUtils.registerEnvironmentBeans(beanFactory,this.servletContext,this.servletConfig); } public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { Assert.notNull(beanPostProcessor,"BeanPostProcessor must not be null"); // Remove from old position,if any this.beanPostProcessors.remove(beanPostProcessor); // Track whether it is instantiation/destruction aware if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { this.hasInstantiationAwareBeanPostProcessors = true; } if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) { this.hasDestructionAwareBeanPostProcessors = true; } // Add to end of list this.beanPostProcessors.add(beanPostProcessor); }
分別將hasInstantiationAwareBeanPostProcessors、hasDestructionAwareBeanPostProcessors屬性都設定成了true,可以猜一下它們有什麼作用。
兩個重要的Processor
在將上下文環境設定完成後,就是通過invokeBeanFactoryPostProcessors方法完成對BeanDefinitionRegistry以及BeanFactory的後置處理器的處理和呼叫,也就是依次呼叫BeanDefinitionRegistryPostProcessor介面和BeanFactoryPostProcessor介面的實現類。
我們可以通過實現這兩個介面在在BeanDefinition註冊完成後,物件例項化之前對容器中的BeanDefinition進行動態的增刪查改,比如Spring中@Configuration註解的解析就是在這個過程中實現的。我們先來了解一下Spring內建的Processor實現有哪些:
整個體系需要有個大概的印象,其中重點關注ConfigurationClassPostProcessor類,該類就是完成對@Configuration、@Bean等註解的解析註冊,這一塊的原始碼這裡暫時不分析。繼續開始的流程,進入到
invokeBeanFactoryPostProcessors方法: protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // getBeanFactoryPostProcessors方法一般是獲取不到值的,除非我們手動呼叫addBeanFactoryPostProcessor方法新增進去, // 換言之我們可以通過註解@Component或是手動呼叫addBeanFactoryPostProcessor方法來注入BeanFactoryPostProcessors物件 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory,getBeanFactoryPostProcessors()); 省略...... }
這裡面 通過委託模式呼叫PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法,並傳入了BeanFactory和Processors物件,但需要注意getBeanFactoryPostProcessors方法不是獲取通過xml配置和Component註解註冊到容器中的Processor物件,而是獲取通過呼叫AbstractApplicationContext.addBeanFactoryPostProcessor方法新增的類,換言之我們實現了Processor介面後可以不在類上新增@Component,直接呼叫addBeanFactoryPostProcessor方法即可,但需要注意,這種方式並沒有對應的BeanDefinition類,新增的物件也不存在於IOC容器中。
繼續進入invokeBeanFactoryPostProcessors方法:
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory,List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first,if any. Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); // 優先處理通過addBeanFactoryPostProcessor方法新增的BeanFactoryPostProcessor for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { // 優先處理BeanDefinitionRegistryPostProcessor物件 if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); //獲取實現了BeanDefinitionRegistryPostProcessor介面的所有類的BeanDefinition物件的beanName String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,true,false); for (String ppName : postProcessorNames) { //判斷是否實現了排序介面 PriorityOrdered if (beanFactory.isTypeMatch(ppName,PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } //排序 sortPostProcessors(currentRegistryProcessors,beanFactory); registryProcessors.addAll(currentRegistryProcessors); //呼叫過程 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry); currentRegistryProcessors.clear(); // Next,invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,false); for (String ppName : postProcessorNames) { //判斷是否是實現的Ordered介面 if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName,Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors,beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry); currentRegistryProcessors.clear(); //沒實現排序介面的呼叫 boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors,beanFactory); registryProcessors.addAll(currentRegistryProcessors); // invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry); currentRegistryProcessors.clear(); } //呼叫postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(registryProcessors,beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors,beanFactory); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors,beanFactory); } //獲取實現了BeanFactoryPostProcessor介面的類,獲取beanDefinition的名稱 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class,false); List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } //實現了PriorityOrdered介面的 else if (beanFactory.isTypeMatch(ppName,PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName,BeanFactoryPostProcessor.class)); } //實現了Ordered介面的 else if (beanFactory.isTypeMatch(ppName,Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { //沒實現介面的 nonOrderedPostProcessorNames.add(ppName); } } //排序 // First,invoke the BeanFactoryPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors,beanFactory); //呼叫 invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors,beanFactory); // Next,invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName,BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors,beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors,beanFactory); List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName,BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors,beanFactory); beanFactory.clearMetadataCache(); }
這個方法很長,但邏輯並不複雜。首先判斷傳入的BeanFactory物件是不是BeanDefinitionRegistry物件,是的話則優先呼叫傳入的Processor物件的postProcessBeanDefinitionRegistry方法,之後再通過beanFactory.getBeanNamesForType拿到容器中所有BeanDefinitionRegistryPostProcessor實現類的名字,然後依次例項化並呼叫實現了PriorityOrdered、Ordered介面(前者優先順序高於後者,數字越小優先順序越高)的Processor的postProcessBeanDefinitionRegistry方法,最後再例項化並呼叫剩餘未實現排序介面的Processor的方法。當所有BeanDefinitionRegistryPostProcessor實現類呼叫完成後,會依次呼叫來自於父介面BeanFactoryPostProcessor的postProcessBeanFactory方法。
上述流程處理完成後,又會通過beanFactory.getBeanNamesForType拿到容器中所有BeanFactoryPostProcessor實現類的名字,處理流程和上面一樣。
註冊BeanPostProcessor物件
以上就是兩個擴充套件點的呼叫流程,完成之後又會呼叫registerBeanPostProcessors註冊所有BeanPostProcessor的子類到容器中來,這個介面也是Spring的一個重要的擴充套件點,它包含了兩個方法:
@Nullable default Object postProcessBeforeInitialization(Object bean,String beanName) throws BeansException { return bean; } @Nullable default Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException { return bean; }
實現了該介面的物件在例項化之前和之後分別會呼叫這兩個方法。同樣,我們先來了解下該介面的繼承體系:
可以看到這個介面Spring內建的實現就比較多,可見用途之廣泛。另外上面畫紅框的是本次需要重點記憶的類,後面Bean例項化時會出現。接著我們來看看registerBeanPostProcessors的實現邏輯:
public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory,AbstractApplicationContext applicationContext) { //拿到工程裡面所有實現了BeanPostProcessor介面的類,獲取到BeanDefinition的名稱 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class,false); int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory,beanProcessorTargetCount)); List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); //提前例項化BeanPostProcessor型別的bean,然後bean進行排序 for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName,PriorityOrdered.class)) { //getBean是例項化方法,後面我們在講bean例項化過程是會著重講到 BeanPostProcessor pp = beanFactory.getBean(ppName,BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); //判斷型別是否是MergedBeanDefinitionPostProcessor,如果是則程式碼是內部使用的 if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } else if (beanFactory.isTypeMatch(ppName,Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First,register the BeanPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors,beanFactory); //註冊到BeanFactory中 registerBeanPostProcessors(beanFactory,priorityOrderedPostProcessors); // Next,register the BeanPostProcessors that implement Ordered. List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(); for (String ppName : orderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName,BeanPostProcessor.class); orderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } sortPostProcessors(orderedPostProcessors,beanFactory); registerBeanPostProcessors(beanFactory,orderedPostProcessors); // Now,register all regular BeanPostProcessors. List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(); for (String ppName : nonOrderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName,BeanPostProcessor.class); nonOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } registerBeanPostProcessors(beanFactory,nonOrderedPostProcessors); // Finally,re-register all internal BeanPostProcessors. sortPostProcessors(internalPostProcessors,internalPostProcessors); // Re-register post-processor for detecting inner beans as ApplicationListeners,// moving it to the end of the processor chain (for picking up proxies etc). beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }
這段程式碼的實現邏輯也很簡單,也是先區分優先順序,再獲取Bean例項,最後註冊到容器中,等到Bean例項化時呼叫。
接下來在refresh方法中呼叫了initMessageSource、initApplicationEventMulticaster、onRefresh、registerListeners,分別是初始化國際化資源、初始化時間廣播器、容器重新整理事件(子類回撥)、註冊監聽器,這幾個方法都很簡單,自己看看就行,這裡就不詳細闡述了。
Bean物件的建立
當所有的準備工作都做好後,就該開始初始化Bean例項了,也就是finishBeanFactoryInitialization方法所做的事。不過這裡可不是根據BeanDefinition new一個物件就完了,它包含了以下幾個工作:
1、初始化例項
2、解析@PostConstruct,@PreDestroy,@Resource, @Autowired,@Value等註解
3、依賴注入
4、呼叫BeanPostProcessor方法
5、AOP入口(本篇暫不分析)
下面就來詳細分析Bean例項化的整個流程:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { ...... //重點看這個方法 // Instantiate all remaining (non-lazy-init) singletons. beanFactory.preInstantiateSingletons(); } public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap,it does otherwise work fine. // xml解析時,講過,把所有beanName都快取到beanDefinitionNames了 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... for (String beanName : beanNames) { // 把父BeanDefinition裡面的屬性拿到子BeanDefinition中 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //如果不是抽象的,單例的,非懶載入的就例項化 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { //判斷bean是否實現了FactoryBean介面,這裡可以不看 if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { final FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { //主要從這裡進入,看看例項化過程 getBean(beanName); } } } }
在preInstantiateSingletons方法中可以看到這裡有一個判斷:單例、非懶載入、非抽象,滿足這三個條件才會呼叫getBean(Bean例項化都是通過呼叫該方法實現的)例項化:
public Object getBean(String name) throws BeansException { return doGetBean(name,null,false); } protected <T> T doGetBean(final String name,@Nullable final Class<T> requiredType,@Nullable final Object[] args,boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); System.out.println("====beanName=="+beanName+"===instance begin===="); Object bean; //從快取中拿例項 Object sharedInstance = getSingleton(beanName); //如果快取裡面能拿到例項 if (sharedInstance != null && args == null) { // 該方法是FactoryBean介面的呼叫入口 bean = getObjectForBeanInstance(sharedInstance,name,beanName,null); } else { //如果快取裡面沒有,則走下來 //如果是scope 是Prototype的,校驗是否有出現迴圈依賴,如果有則直接報錯 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup,requiredType,args,typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup,args); } else if (requiredType != null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup,requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { // 父子BeanDefinition合併 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 檢驗是不是抽象類,是直接丟擲異常 checkMergedBeanDefinition(mbd,args); // 獲取依賴物件屬性,依賴物件要先例項化 // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName,dep)) { throw new BeanCreationException(mbd.getResourceDescription(),"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep,beanName); try { //例項化 getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(),"'" + beanName + "' depends on missing bean '" + dep + "'",ex); } } } //大部分是單例的情況 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName,() -> { try { return createBean(beanName,mbd,args); } }); // 該方法是FactoryBean介面的呼叫入口 bean = getObjectForBeanInstance(sharedInstance,mbd); } else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName,args); } finally { afterPrototypeCreation(beanName); } // 該方法是FactoryBean介面的呼叫入口 bean = getObjectForBeanInstance(prototypeInstance,mbd); } else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName,() -> { beforePrototypeCreation(beanName); try { return createBean(beanName,args); } finally { afterPrototypeCreation(beanName); } }); // 該方法是FactoryBean介面的呼叫入口 bean = getObjectForBeanInstance(scopedInstance,mbd); } } } } return (T) bean; }
這段程式碼首先從快取裡面拿到單例物件,如果沒有,則通過scope型別去建立對應的Bean例項(直接建立或是通過getObjectForBeanInstance呼叫FactoryBean介面的方法建立)。在建立物件之前如果scope是prototype型別的首先會通過isPrototypeCurrentlyInCreation檢驗是否存在迴圈依賴(迴圈依賴這裡先不講),存在直接丟擲異常,原型物件不允許有迴圈依賴出現;校驗完成後還會通過mbd.getDependsOn拿到@DependsOn註解的值,如果有,則會優先例項化依賴的物件。
因為大部分都是建立單例物件,所以下面我以getSingleton方法來分析,需要注意該方法傳入了一個Lambda表示式,在該表示式中呼叫了createBean方法,觀察其它scope建立bean會發現都呼叫了該方法,所以實際建立bean物件就是該方法,不過我們還是先進入getSingleton方法看看做了些什麼:
public Object getSingleton(String beanName,ObjectFactory<?> singletonFactory) { Assert.notNull(beanName,"Bean name must not be null"); 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 singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } // 把beanName新增到singletonsCurrentlyInCreation Set容器中,在這個集合裡面的bean都是正在例項化的bean beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { // 如果這裡有返回值,就代表這個bean已經結束建立了,已經完全建立成功 singletonObject = singletonFactory.getObject(); newSingleton = true; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } //bean建立完成後singletonsCurrentlyInCreation要刪除該bean afterSingletonCreation(beanName); } if (newSingleton) { System.out.println("====beanName==" + beanName + "===instance end===="); // 建立物件成功時,把物件快取到singletonObjects快取中,bean建立完成時放入一級快取 addSingleton(beanName,singletonObject); } } return singletonObject; } }
這個方法裡面首先是從快取中獲取物件,如果有直接返回,如果沒有則將該物件的beanName加入到singletonsCurrentlyInCreation快取中,如果新增不成功,說明已經有其它地方正在建立該物件,當前建立直接丟擲異常,如果新增成功,則呼叫singletonFactory.getObject去建立物件,這個方法就是傳入的Lambda表示式,建立完成後刪除掉singletonsCurrentlyInCreation快取中的值並將物件新增到一級快取,後續需要該物件時,都是從一級快取中獲取的。
在getObject中通過createBean去建立物件,而該方法又呼叫了doCreateBean,我們直接來看這個方法:
protected Object doCreateBean(final String beanName,final RootBeanDefinition mbd,final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //建立例項,重點看 instanceWrapper = createBeanInstance(beanName,args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { // Bean例項化完成後收集類中的註解(@PostConstruct,@PreDestroy,@Resource, @Autowired,@Value) applyMergedBeanDefinitionPostProcessors(mbd,beanType,beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(),"Post-processing of merged bean definition failed",ex); } mbd.postProcessed = true; } } // 單例bean提前暴露 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } // 這裡著重理解,對理解迴圈依賴幫助非常大,新增三級快取 addSingletonFactory(beanName,() -> getEarlyBeanReference(beanName,bean)); } // Initialize the bean instance. Object exposedObject = bean; try { // ioc di,依賴注入的核心方法 populateBean(beanName,instanceWrapper); // bean 例項化+ioc依賴注入完以後的呼叫 exposedObject = initializeBean(beanName,exposedObject,mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(),"Initialization of bean failed",ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName,false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } } } } // Register bean as disposable. try { //註冊bean銷燬時的類DisposableBeanAdapter registerDisposableBeanIfNecessary(beanName,bean,mbd); } return exposedObject; }
這個方法裡面首先去通過createBeanInstance建立物件的例項,建立完成後又通過applyMergedBeanDefinitionPostProcessors收集類中的註解@Autowired、@Value、@PostConstruct,@PreDestroy,@Resource準備依賴注入或是方法呼叫,緊接著呼叫addSingletonFactory新增三級快取處理迴圈依賴,之後通過populateBean依賴注入真正完成一個完整物件的建立,最後在initializeBean中觸發事件和一些方法的呼叫。
下面逐個分析這些方法。
createBeanInstance
protected BeanWrapper createBeanInstance(String beanName,RootBeanDefinition mbd,@Nullable Object[] args) { // Make sure bean class is actually resolved at this point. //反射拿到Class物件 Class<?> beanClass = resolveBeanClass(mbd,beanName); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(),"Bean class isn't public,and non-public access not allowed: " + beanClass.getName()); } Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier,beanName); } // 在xml配置bean時指定factory-bean屬性和factory-method以及@Bean註解 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName,args); } // Candidate constructors for autowiring? //尋找當前正在例項化的bean中有@Autowired註解的建構函式 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass,beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { //如果ctors不為空,就說明建構函式上有@Autowired註解 return autowireConstructor(beanName,ctors,args); } // Preferred constructors for default construction? ctors = mbd.getPreferredConstructors(); if (ctors != null) { return autowireConstructor(beanName,null); } //無參建構函式的例項化,大部分的例項是採用的無參建構函式的方式例項化 // No special handling: simply use no-arg constructor. return instantiateBean(beanName,mbd); }
在這個方法裡面又做了很多判斷,首先是拿到factoryMethodName,當我們在xml配置bean時指定了factory-bean屬性和factory-method屬性或者是使用了@Bean註解時這裡就會拿到值,然後就會通過FactoryMethod去建立一個例項物件;如果不存在factoryMethodName,那麼就需要通過建構函式來例項化物件,但建構函式上可能存在註解@Autowired,因此需要通過determineConstructorsFromBeanPostProcessors獲取到所有帶@Autowired註解的建構函式:
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass,String beanName) throws BeansException { /** * 通過AutowiredAnnotationBeanPostProcessor(在component-scan解析時 * 通過registerComponents方法註冊的,然後又在refresh中呼叫registerBeanPostProcessors方法 * 例項化的)類找到標記了@Autowired註解的建構函式 */ if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass,beanName); if (ctors != null) { return ctors; } } } } return null; }
拿到所有帶@Autowired註解的建構函式後就是通過呼叫autowireConstructor來進行例項化,具體則是通過委託給ConstructorResolver類進行處理,包括上面通過factoryMethod建立物件也是委託給這個類。如果沒有帶@Autowired的建構函式才會呼叫instantiateBean方法,利用反射通過無參建構函式去建立物件並返回,也是大部分物件例項化所走的流程。
至此,簡單物件的例項化完成。
addSingletonFactory
這個方法就是新增三級快取解決迴圈依賴問題,暫時不分析。
populateBean
protected void populateBean(String beanName,@Nullable BeanWrapper bw) { boolean continueWithPropertyPopulation = true; // 這裡可以寫介面可以讓所有類都不能依賴注入,沒有什麼實際作用 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(),beanName)) { //是否需要DI,依賴注入 continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName,bw,newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName,newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; //重點看這個if程式碼塊 if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; //依賴注入過程,@Autowired的支援 PropertyValues pvsToUse = ibp.postProcessProperties(pvs,bw.getWrappedInstance(),beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw,mbd.allowCaching); } //老版本用這個完成依賴注入過程,@Autowired的支援 pvsToUse = ibp.postProcessPropertyValues(pvs,filteredPds,beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw,mbd.allowCaching); } checkDependencies(beanName,pvs); } // xml中<property>標籤的依賴注入 if (pvs != null) { applyPropertyValues(beanName,pvs); } }
這裡面主要有三個方法是完成依賴注入的:postProcessProperties(當前主要使用)、postProcessPropertyValues(老版本廢棄API)、applyPropertyValues(xml中property標籤)。
所以主要看看postProcessProperties方法,而這個方法又是來自於InstantiationAwareBeanPostProcessor介面(希望你還記得這個介面的繼承體系),主要看看AutowiredAnnotationBeanPostProcessor,這個就是解決@Autowired依賴注入的。
public PropertyValues postProcessProperties(PropertyValues pvs,Object bean,String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName,bean.getClass(),pvs); try { metadata.inject(bean,pvs); } return pvs; }
見名知意,findAutowiringMetadata方法就是拿到@Autowired註解的屬性並封裝為InjectionMetadata物件,再呼叫inject進行依賴注入,注意這裡是包含了屬性和方法的(方法也不一定是setter方法才可以,只要是標記了@Autowired且引數型別正確都能依賴成功)。
這就是@Autowired的注入過程,另外還有@Resource的注入,在CommonAnnotationBeanPostProcessor類中,流程和這個基本一樣,這裡就不闡述了。
initializeBean
以上過程都是對Bean的例項化,以及物件中屬性的注入,都完成過後這個Bean物件才是我們真正可以直接使用的物件,所以接著就是處理一些方法的呼叫了(包含一些事件通知)。
protected Object initializeBean(final String beanName,final Object bean,@Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName,bean); return null; },getAccessControlContext()); } else { // 呼叫Aware方法 invokeAwareMethods(beanName,bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //對類中某些特殊方法的呼叫,比如@PostConstruct,Aware介面 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName); } try { //InitializingBean介面,afterPropertiesSet,init-method屬性呼叫,非常重要 invokeInitMethods(beanName,wrappedBean,mbd); } if (mbd == null || !mbd.isSynthetic()) { // 這個地方可能生出代理例項,是aop的入口 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean,beanName); } return wrappedBean; } private void invokeAwareMethods(final String beanName,final Object bean) { if (bean instanceof Aware) { // 實現該介面可以在bean例項化完成後獲取到bean的名稱 if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } // 實現該介面可以在bean例項化完成後獲取到當前的類載入器 if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } // 實現該介面可以在bean例項化完成後獲取到當前的AbstractAutowireCapableBeanFactory物件 if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
首先是Aware介面的方法呼叫,這個很簡單不多說。接著就是applyBeanPostProcessorsBeforeInitialization方法呼叫,這個就是BeanPostProcessor介面的postProcessBeforeInitialization方法呼叫(看到這裡你是否會發現自己之前理解錯了呢,以為該方法是在物件例項化之前呼叫,實際上也是例項化完成之後):
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean,String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessBeforeInitialization(result,beanName); if (current == null) { return result; } result = current; } return result; }
這裡面著重看幾個實現類的呼叫:ApplicationContextAwareProcessor(ApplicationEventPublisherAware、ApplicationContextAware等Aware介面的呼叫)、InitDestroyAnnotationBeanPostProcessor(@PostConstruct註解方法的呼叫)、ImportAwareBeanPostProcessor(ImportAware型別例項setImportMetadata呼叫,對理解SpringBoot幫助很大,這裡可以暫時不看)。
緊著著又通過invokeInitMethods方法呼叫InitializingBean介面的afterPropertiesSet方法以及init-method屬性配置的自定義初始化方法。
最後則是通過applyBeanPostProcessorsAfterInitialization方法呼叫BeanPostProcessor的postProcessAfterInitialization方法,因為涉及到AOP知識,這裡不詳細分析。
至此,Bean的整個例項化過程分析完成,看到這裡,你應該對於Bean的生命週期函式有個基本的認識了,最後放上我畫的Bean例項化流程時序圖:
總結
本篇篇幅很長,中間很多無關痛癢的程式碼我都省略掉了,也有一些無關主流程但也比較重要的程式碼沒有分析,比如ConfigurationClassPostProcessor解析@Configuration、@Bean註解的過程,FactoryMethod建立物件過程、獲取@Autowired註解標記的建構函式以及通過這些建構函式例項化過程我都沒有分析,一來是限於篇幅過長,二來主要是因為對理解整個流程並沒有太大作用並且程式碼相對更簡單,感興趣的讀者可在理解清楚主流程後自行分析。