Java 圖解Spring啟動時的後置處理器工作流程是怎樣的
探究Spring的後置處理器
本次我們主要探究invokeBeanFactoryPostProcessors()
;後面的代碼下次再做解析;
入口代碼refresh()
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // ...... applicationContext.refresh();
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. // 啟動前的準備工作:記錄啟動時間,活動標記為啟動以及環境屬性變量集合的初始化 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. //還是一些準備工作,添加瞭兩個後置處理器:ApplicationContextAwareProcessor,ApplicationListenerDetector //還設置瞭 忽略自動裝配 和 允許自動裝配 的接口 //對環境,系統環境,系統屬性三個Bean如果不存在某個bean的時候,spring就自動生成singleton bean(Not bd) //還設置瞭bean表達式解析器 等 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. // 空方法 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //執行自定義的BeanFactoryProcessor和內置的BeanFactoryProcessor invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
流程圖
prepareRefresh剖析
該方法主要做啟動前的準備工作:記錄啟動時間,活動標記為啟動以及環境屬性變量集合的初始化;
protected void prepareRefresh() { // Switch to active. this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); // Initialize any placeholder property sources in the context environment. // 空方法 initPropertySources(); // Validate that all properties marked as required are resolvable: // see ConfigurablePropertyResolver#setRequiredProperties getEnvironment().validateRequiredProperties(); // Store pre-refresh ApplicationListeners... if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { // Reset local application listeners to pre-refresh state. this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... this.earlyApplicationEvents = new LinkedHashSet<>(); }
obtainFreshBeanFactory刨析
主要是獲取context上下文中的bean工廠;
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // CAS保證同步 refreshBeanFactory(); // 返回beanFactory- DefaultListableBeanFactory.class ConfigurableListableBeanFactory beanFactory = getBeanFactory(); return beanFactory; }
prepareBeanFactory刨析
做一些準備工作,添加瞭兩個後置處理器ApplicationContextAwareProcessor
和ApplicationListenerDetector
;
設置瞭bean表達式解析器等;
通過工廠的接口可以設置瞭忽略自動裝配,和允許自動裝配;
對環境、系統環境、系統屬性三個Bean如果不存在某個bean的時候,spring就自動生成singletonBean(Not bd);
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to use the context's class loader etc. beanFactory.setBeanClassLoader(getClassLoader()); //設置bean表達式解析器 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); //屬性編輯器支持 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // Configure the bean factory with context callbacks. //添加一個後置處理器:ApplicationContextAwareProcessor,此後置處理處理器實現瞭BeanPostProcessor接口 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); //以下接口,忽略自動裝配 beanFactory.ignoreDependencyInterface(EnvironmentAware.class); // ..... // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean. //以下接口,允許自動裝配,第一個參數是自動裝配的類型,,第二個字段是自動裝配的值 // 這個接口僅會將註入的參數XXX.class註入為指定的值,但不影響XXX.class創建Bean對象; beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); // Register default environment beans. // 環境,系統環境,系統屬性 因此通常情況下,這三個Bean是沒有bd的 //如果沒有註冊過bean名稱為XXX,spring就自己創建一個名稱為XXX的singleton bean if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }
invokeBeanFactoryPostProcessors剖析
執行自定義的BeanFactoryProcessor
和內置的BeanFactoryProcessor
;
getBeanFactoryPostProcessors()
方法是我們手動通過執行addBeanFactoryPostProcessor(XX)
設置自定義的後置處理器。如果初始化執行到這,沒有手動增加後置處理器的話,那麼此時List<BeanFactoryPostProcessor>
的size()為empty;
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // getBeanFactoryPostProcessors是spring允許我們手動添加BeanFactoryPostProcessor // 即:annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX); // 未手動添加的話,getBeanFactoryPostProcessors()為empty PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor) if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }
我們通過委托PostProcessorRegistrationDelegate
去調用invokeBeanFactoryPostProcessors()
方法,從而去掃描並執行BeanFactoryProcessor
和BeanDefinitionRegistryPostProcessor
;
我們通過繼承關系看,BeanDefinitionRegistryPostProcessor
實際上是繼承BeanFactoryProcessor
接口的;
BeanDefinitionRegistryPostProcessor
:主要掃描類解析類;BeanFactoryProcessor
:主要給配置類進行增強代理;
這裡面需要看我們的BeanFactory的類型;初始時BeanFactory的類型是DefaultListableBeanFactory
;因此,該bean工廠是實現BeanDefinitionRegistry
;
該方法的具體流程如下(按初始化進入到這裡描述):
- 循環遍歷手動添加的後置處理器(並不排序);
- 若該bfp是bdrp則直接執行
bdrp. postProcessBeanDefinitionRegistry()
; - 取出內置的bdrp,分為實現瞭
PriorityOrdered
,Ordered
和都沒有實現的三類;
初始這裡隻有一個,就是我們在初始化reader()時,註冊瞭一個ConfigurationClassPostProcessor.class
;
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {}
將上面三類直接執行bdrp. postProcessBeanDefinitionRegistry()
;
然後將手動加入和內置的bdrp執行bfp.postProcessBeanFactory()
;
上面的已經執行完瞭:
- 手動添加的後置處理器的
bdrf. postProcessBeanDefinitionRegistry()
和bfp.postProcessBeanFactory()
; - 內置的
bdrp. postProcessBeanDefinitionRegistry()
取出內置的bfp,分為實現瞭PriorityOrdered
, Ordered
和都沒有實現的三類;
目前這裡內置的有兩個。但其中config上面已經執行過瞭,此處隻執行下方的一個;
將上面三類直接執行bfp. postProcessBeanDefinitionRegistry()
;
清除緩存中的bd,因為後處理器可能有修改瞭原始元數據,例如替換值中的占位符;
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. Set<String> processedBeans = new HashSet<>(); // 如果不是BeanDefinitionRegistry 則直接執行beanFactoryPostProcessors // 剛啟動時傳入的beanFactory是DefaultListableBeanFactory,他是實現瞭BeanDefinitionRegistry 因此會走這裡 if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; // bf後置處理器集合(手動添加與bdr後置處理器集合【下面的那個集合】):因為bdrp屬於bfp List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); // bdr後置處理器集合(手動添加與spring自己的) List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); // 循環傳進來的beanFactoryPostProcessors,剛啟動時未手動增加的情況下beanFactoryPostProcessors肯定沒有數據 // 因為beanFactoryPostProcessors是獲得手動添加的,而不是spring掃描的 // 隻有手動調用annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX)才會有數據 // 執行手動添加的beanFactoryPostProcessors, 如果是BeanDefinitionRegistryPostProcessor,則執行其postProcessBeanDefinitionRegistry再加到list中 for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } //一個臨時變量,用來裝載BeanDefinitionRegistryPostProcessor為瞭排序 //BeanDefinitionRegistry繼承瞭PostProcessorBeanFactoryPostProcessor List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // 獲得實現BeanDefinitionRegistryPostProcessor接口的類 // 就是ConfigurationClassPostProcessor(Spring自己添加的-在reader()時增加的) String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { //獲得ConfigurationClassPostProcessor類,並且放到currentRegistryProcessors //ConfigurationClassPostProcessor是很重要的一個類,它實現瞭BeanDefinitionRegistryPostProcessor接口 //BeanDefinitionRegistryPostProcessor接口又實現瞭BeanFactoryPostProcessor接口 //ConfigurationClassPostProcessor是極其重要的類 //裡面執行瞭掃描Bean,Import,ImportResouce等各種操作 //用來處理配置類(有兩種情況 一種是傳統意義上的配置類,一種是普通的bean)的各種邏輯 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); //把name放到processedBeans,後續會根據這個集合來判斷處理器是否已經被執行過瞭 processedBeans.add(ppName); } } //處理排序 sortPostProcessors(currentRegistryProcessors, beanFactory); //合並Processors,為什麼要合並,因為registryProcessors是裝載BeanDefinitionRegistryPostProcessor的 //一開始的時候,spring隻會執行BeanDefinitionRegistryPostProcessor獨有的方法 //而不會執行BeanDefinitionRegistryPostProcessor父類的方法,即BeanFactoryProcessor的方法 //所以這裡需要把處理器放入一個集合中,後續統一執行父類的方法 registryProcessors.addAll(currentRegistryProcessors); //可以理解為執行ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法 //Spring熱插播的體現,像ConfigurationClassPostProcessor就相當於一個組件,Spring很多事情就是交給組件去管理 //將spring提供的RegistryProcessors(就是這個ConfigurationClassPostProcessor)執行其postProcessBeanDefinitionRegistry invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); //清空臨時變量 currentRegistryProcessors.clear(); // 再次根據BeanDefinitionRegistryPostProcessor獲得BeanName,看這個BeanName是否已經被執行過瞭,有沒有實現Ordered接口 // 如果沒有被執行過,也實現瞭Ordered接口的話,把對象推送到currentRegistryProcessors,名稱推送到processedBeans // 如果沒有實現Ordered接口的話,這裡不把數據加到currentRegistryProcessors,processedBeans中,後續再做處理 // 這裡才可以獲得我們定義的實現瞭BeanDefinitionRegistryPostProcessor的Bean postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } //處理排序 sortPostProcessors(currentRegistryProcessors, beanFactory); //合並Processors registryProcessors.addAll(currentRegistryProcessors); //執行有Ordered的BeanDefinitionRegistryPostProcessor invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); //清空臨時變量 currentRegistryProcessors.clear(); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. // 下面的代碼就是執行沒有實現PriorityOrdered接口也沒有Ordered的BeanDefinitionRegistryPostProcessor boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, 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(); } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. //registryProcessors集合裝載BeanDefinitionRegistryPostProcessor //上面的代碼是執行bfr後置處理器子類獨有的方法,這裡需要再把bfr後置處理器父類的方法也執行一次 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); //regularPostProcessors裝載BeanFactoryPostProcessor,執行BeanFactoryPostProcessor的方法 //但是regularPostProcessors一般情況下,是不會有數據的,隻有在外面手動添加BeanFactoryPostProcessor,才會有數據 invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. // 若bfp沒有繼承bdrp則直接執行手動增加bf後置處理器的後置處理器 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // 找到BeanFactoryPostProcessor實現類的BeanName數組 // 處理Spring自己的bf後置處理器 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. // PriorityOrdered的bf後置處理器集合 List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); // Ordered的bf後置處理器集合 List<String> orderedPostProcessorNames = new ArrayList<>(); // 無PriorityOrdered無Ordered的bf後置處理器集合 List<String> nonOrderedPostProcessorNames = new ArrayList<>(); //循環BeanName數組 for (String ppName : postProcessorNames) { //如果這個Bean被執行過瞭,跳過 if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } //如果實現瞭PriorityOrdered接口,加入到priorityOrderedPostProcessors else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } //如果實現瞭Ordered接口,加入到orderedPostProcessorNames else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } //如果既沒有實現PriorityOrdered,也沒有實現Ordered。加入到nonOrderedPostProcessorNames else { nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. //排序處理priorityOrderedPostProcessors,即實現瞭PriorityOrdered接口的BeanFactoryPostProcessor sortPostProcessors(priorityOrderedPostProcessors, beanFactory); //執行priorityOrderedPostProcessors invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. //執行實現瞭Ordered接口的BeanFactoryPostProcessor List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. // 執行既沒有實現PriorityOrdered接口,也沒有實現Ordered接口的BeanFactoryPostProcessor List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // Clear cached merged bean definitions since the post-processors might have // modified the original metadata, e.g. replacing placeholders in values... // 清除瞭allBeanNamesByType&singletonBeanNamesByType() // 清除緩存中的bd,因為後處理器可能有修改瞭原始元數據,例如替換值中的占位符 beanFactory.clearMetadataCache(); }
到此這篇關於Java 圖解Spring啟動時的後置處理器工作流程是怎樣的的文章就介紹到這瞭,更多相關Java Spring 後置處理器內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Spring的BeanFactoryPostProcessor接口示例代碼詳解
- Spring源碼BeanFactoryPostProcessor詳解
- Spring源碼解析之Configuration
- Java 確保某個Bean類被最後執行的幾種實現方式
- 詳解Spring ApplicationContext加載過程