Spring的BeanFactoryPostProcessor接口示例代碼詳解
接口簡介
BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 時對外暴露的擴展點,Spring IoC 容器允許 BeanFactoryPostProcessor 在容器實例化任何 bean 之前讀取 bean 的定義,並可以修改它。
BeanDefinitionRegistryPostProcessor 繼承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的優先級,主要用來在常規的 BeanFactoryPostProcessor 檢測開始之前註冊其他 bean 定義。特別是,你可以通過 BeanDefinitionRegistryPostProcessor 來註冊一些常規的 BeanFactoryPostProcessor,因為此時所有常規的 BeanFactoryPostProcessor 都還沒開始被處理。
註意點:通過BeanDefinitionRegistryPostProcessor 註冊的 BeanDefinitionRegistryPostProcessor 接口的postProcessBeanDefinitionRegistry方法將得不到調用,具體的原因會在下面的代碼中解釋。
BeanFactoryPostProcessor 接口調用機制
BeanFactoryPostProcessor 接口的調用在 AbstractApplicationContext#invokeBeanFactoryPostProcessors方法中。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { 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(beanFactory, getBeanFactoryPostProcessors())方法:
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // 用於存放已經處理過的Bean名字 Set<String> processedBeans = new HashSet<>(); // 一般會進入這個判斷 if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; // 所謂的regularPostProcessors就是指實現BeanFactoryPostProcessor接口的Bean List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); // 所謂的registryProcessors就是指實現BeanDefinitionRegistryPostProcessor接口的Bean List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); // 這邊遍歷的是通過ApplicationContext接口註冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口 // 需要和BeanFactory中BeanDefinitionMap中的BeanFactoryPostProcessor接口區分開 for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; //如果是BeanDefinitionRegistryPostProcessor,則先進行postProcessBeanDefinitionRegistry處理,這個方法一般進行BeanDefinition註冊,從這邊可以看出BeanDefinitionRegistryPostProcessor接口的方法先調用,所以優先級高於BeanFactoryPostProcessor // 通過這個代碼可以看出,通過ApplicationContext直接註冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor並不支持Order接口,而是根據註冊的順序執行 registryProcessor.postProcessBeanDefinitionRegistry(registry); // 保存這個BeanDefinitionRegistryPostProcessor,因為還要執行這個類的BeanFactoryPostProcessor方法; registryProcessors.add(registryProcessor); } else { // 保存,後面還要執行這個類的BeanFactoryPostProcessor方法; regularPostProcessors.add(postProcessor); } } List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // 這邊獲取的是BeanFactory中的BeanDefinitionRegistryPostProcessor String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { //先處理PriorityOrdered標註的BeanDefinitionRegistryPostProcessor if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); //將其標記為已經處理,防止重復處理 processedBeans.add(ppName); } } // 將其排序,以便按順序處理 sortPostProcessors(currentRegistryProcessors, beanFactory); // 將其保存,以便處理這個類的BeanFactoryPostProcessor方法 registryProcessors.addAll(currentRegistryProcessors); // 執行BeanDefinitionRegistryPostProcessor接口方法 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // 清除,以便開始處理@Order標註的註解 currentRegistryProcessors.clear(); // 註意:這邊重新獲取BeanDefinitionRegistryPostProcessor是有深意的,因為上面在處理@PriorityOrdered標註的BeanDefinitionRegistryPostProcessor時可能又註入瞭新的BeanDefinitionRegistryPostProcessor。 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); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // 處理不標註註解的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(); } // 調用postProcessBeanFactory 方法,所以BeanDefinitionRegistryPostProcessor中的postProcessBeanFactory方法的優先級要高。 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // 開始處理BeanFactoryPostProcessor接口 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // 也是按照@PriorityOrdered @Ordered 和普通的方式進行處理 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 } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // 先執行@PriorityOrdered標註的接口 sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // 處理@Order標註的類 List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); for (String postProcessorName : orderedPostProcessorNames) { // 這邊通過名字重新拿瞭Bean,應該是怕上面的處理改變瞭Bean orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // 最後調用普通的BeanFactoryPostProcessor List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); 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... beanFactory.clearMetadataCache(); }
簡單總結
上面的方法看起來很長很復雜,但其實幹的事情並不多,就調用瞭BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口的實現。這邊再簡單總結下具體的過程:
step1:執行通過ApplicationContext#addBeanFactoryPostProcessor()方法註冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor。
具體過程如下:假如通過ApplicationContext註冊瞭一個BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,那麼會先執行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,但是BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法和BeanFactoryPostProcessor的postProcessBeanFactory方法暫時都不會在這步執行。
另外需要註意的是:通過ApplicationContext註冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor都不支持@PriorityOrdered和@Ordered順序處理,而是按照我們添加的順序處理
step2:處理BeanFactory中的BeanDefinitionRegistryPostProcessor,處理的順序是先處理@PriorityOrdered標註的,再處理@Ordered標註的,最後處理普通的BeanDefinitionRegistryPostProcessor。到這邊,所有BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法都已經調用完畢,下面就開始處理BeanFactoryPostProcessor的postProcessBeanFactory方法。
step3:調用BeanDefinitionRegistryPostProcessor實現的postProcessBeanFactory方法(因為BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口)
step4:調用通過ApplicationContext#addBeanFactoryPostProcessor()註冊的“單純”的BeanFactoryPostProcessor
step5:調用BeanFactory中的BeanFactoryPostProcessor,調用順序也是按照@PriorityOrdered和@Ordered順序處理,沒有這兩個註解的最後處理。
好瞭,到這邊BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口就已經處理完瞭。後面我們會拿ConfigurationClassPostProcessor 這個特殊的BeanDefinitionRegistryPostProcessor做列子講下具體流程,這邊隻是介紹BeanFactoryPostProcessor的調用機制。
到此這篇關於Spring的BeanFactoryPostProcessor接口的文章就介紹到這瞭,更多相關Spring BeanFactoryPostProcessor接口內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Spring源碼BeanFactoryPostProcessor詳解
- Java 圖解Spring啟動時的後置處理器工作流程是怎樣的
- Java 確保某個Bean類被最後執行的幾種實現方式
- Spring源碼解析之Configuration
- 詳解Spring ApplicationContext加載過程