您好,登錄后才能下訂單哦!
本篇文章為大家展示了如何在Spring中實現一個BeanFactoryPostProcessor接口,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 時對外暴露的擴展點,Spring IoC 容器允許 BeanFactoryPostProcessor 在容器實例化任何 bean 之前讀取 bean 的定義,并可以修改它。
BeanDefinitionRegistryPostProcessor 繼承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的優先級,主要用來在常規的 BeanFactoryPostProcessor 檢測開始之前注冊其他 bean 定義。特別是,你可以通過 BeanDefinitionRegistryPostProcessor 來注冊一些常規的 BeanFactoryPostProcessor,因為此時所有常規的 BeanFactoryPostProcessor 都還沒開始被處理。
注意點:通過BeanDefinitionRegistryPostProcessor 注冊的 BeanDefinitionRegistryPostProcessor 接口的postProcessBeanDefinitionRegistry方法將得不到調用,具體的原因會在下面的代碼中解釋。
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接口,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。