日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring重写BeanDefinitionRegistryPostProcessors进行扩展

發布時間:2025/3/19 javascript 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring重写BeanDefinitionRegistryPostProcessors进行扩展 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 1. 前言
  • 2. BeanDefinitionRegistryPostProcessors 作用
  • 3. 代碼示例
  • 4. 底層實現解析
  • 5. 總結

1. 前言

最近項目中遇到這么個問題,公司底層封裝的框架有UserService(接口)和 UserServiceImpl(實現類)。基于此框架開發的項目,通過如下代碼就能直接從Spring容器取出 UserServiceImpl 對象:

@Autowired private UserService userService;

現在有個項目A,UserService.save方法不滿足項目需求。因此在項目中重寫save方法,并且不能修改框架代碼。思來想去,實現的方法可能有多種,但是都比較麻煩。最理想的方案是創建 MyUserServiceImpl 繼承 UserServiceImpl,并重寫相關方法,例如:

public class MyUserServiceImpl: UserServiceImpl {public void onBeforeSave(User user){//各個項目在這里重寫特殊邏輯}public void onAfterSave(User user){//各個項目在這里重寫特殊邏輯} }

思路有了,那還有最后一個問題需要解決:屬性注入 UserService userService 取到的對象是 UserServiceImpl ,怎么自動替換成新增的 MyUserServiceImpl?

為了解決這個問題,就需要用到Spring提供的后置處理器 PostProcessor 。

2. BeanDefinitionRegistryPostProcessors 作用

先看這張圖,大致介紹了 Spring 容器初始化的過程:

如果說 Class 是Java對象的元數據信息,那么 BeanDefinition 就是 Spring Bean 的描述信息。
BeanDefinition 記錄了 Spring Bean 的一些重要字段,例如:scope作用域、lazyInit是否懶加載、dependsOn、beanClassName類名等等

如圖所示,黃色節點的第3點,掃描類的最后一步會執行程序員創建的 BeanDefinitionRegistryPostProcessor 對象。

因此,我們在這一步取出 UserServiceImpl 對應的BeanDefinition,然后將其 BeanClassName 改成 MyUserServiceImpl.class 。最終,在創建Bean的時候就不再創建UserServiceImpl,而是MyUserServiceImpl。

3. 代碼示例

創建接口類 UserService

public interface UserService {void save(); }

創建實現類 UserServiceImpl

@Service public class UserServiceImpl implements UserService {@Overridepublic void save() {onBeforeSave();System.out.println("執行Save方法");onAfterSave();}public void onBeforeSave(){System.out.println("UserServiceImpl.onBeforeSave");}public void onAfterSave(){System.out.println("UserServiceImpl.onAfterSave");} }

創建應用程序啟動類:

@ComponentScan("com.train") public class SpringAnnotationApp {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringAnnotationApp.class);UserService userService = applicationContext.getBean(UserService.class);System.out.println(userService.getClass());userService.save();} }

因為我們還沒做任何處理,所以默認情況創建的是 UserServiceImpl 對象,輸出結果如下

class com.train.service.impl.UserServiceImpl UserServiceImpl.onBeforeSave 執行Save方法 UserServiceImpl.onAfterSave

重點來了,創建 MyBeanDefinitionRegistryPostProcessor 實現 BeanDefinitionRegistryPostProcessor 接口

@Component public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {BeanDefinition beanDefinition = registry.getBeanDefinition("userServiceImpl");beanDefinition.setBeanClassName(MyUserServiceImpl.class.getName());}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {} }

其他代碼不動,重新運行程序,結果變了,達到了我們的要求:

class com.train.inherit.MyUserServiceImpl MyUserServiceImpl.onBeforeSave 執行Save方法 MyUserServiceImpl.onAfterSave

4. 底層實現解析

上面講了應用場景,接下來介紹Spring源碼如何實現的。

跳過無關的代碼,直接查看 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors,以下是核心代碼和相關注釋。主要貼出的是 BeanDefinitionRegistryPostProcessors 部分。

這個類的代碼比較多,還有一部分是 BeanFactoryPostProcessors, 這里先刪掉了

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {Set<String> processedBeans = new HashSet<>();if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();/*** 1.從Spring容器獲取實現 BeanDefinitionRegistryPostProcessor 接口的處理器* 2.到這里為止,我們自己寫的Bean還沒加載到容器,因此,可以理解為此處執行的是Spring自帶的 BeanDefinitionRegistryPostProcessor(實現類是ConfigurationClassPostProcessor)* 3.ConfigurationClassPostProcessor作用是掃描程序員定義的,需要給Spring管理的類,并封裝成BeanDefinition*/String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {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();/*** 1.再次從Spring容器獲取實現 BeanDefinitionRegistryPostProcessor 接口的處理器* 2.排除掉上一步執行過的PostProcessor,剩余的就是程序員定義的PostProcessor* 3.判斷是否實現 Ordered 排序接口,沒有實現就先跳過(保證程序員指定的按順序執行)* 4.執行程序員寫的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();/*** 1.再次從Spring容器獲取實現 BeanDefinitionRegistryPostProcessor 接口的處理器* 2.過濾掉前面2步執行過的PostProcessor,剩余的就是程序員定義的,并且沒有實現 Ordered 排序接口的部分* 3.執行程序員寫的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();}}}

5. 總結

  • 上面的代碼只是舉個例子,如果重寫類較多的話,一個個修改比較麻煩。如果運用到實際項目中,可以采取約定的規則掃描類,然后自動遍歷處理BeanDefinition。
  • Spring 提供的 PostProcessor 目的就是允許程序員對其進行擴展,本文講解的 BeanDefinitionRegistryPostProcessor 到這里就結束了,后面的其他文章將會陸續介紹其他擴展點。
與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的Spring重写BeanDefinitionRegistryPostProcessors进行扩展的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。