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

歡迎訪問 生活随笔!

生活随笔

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

javascript

Spring系列之BeanPostProcessor分析

發布時間:2024/4/13 javascript 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring系列之BeanPostProcessor分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在Spring系列之Bean的生命周期及相關源碼中,我們最后簡單使用過BeanPostProcessor,這次我們就結合源碼來具體談談這個BeanPostProcessor的作用。

實現BeanPostProcessor接口的類

public class TestBeanPostProcessor implements BeanPostProcessor {@Nullable@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessBeforeInitialization——"+beanName+"——"+bean);return bean;}@Nullable@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessAfterInitialization————"+beanName+"——"+bean);return bean;} }

然后我們看一下測試類

public class TestMain {@Testpublic void test(){AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfig.class);} }

我們可以看到除了我們自定義的Dog類被我們自定義的后置處理器TestBeanPostProcessor 增強了之外,還有幾個默認的Bean也被增強了,那Spring容器中還有沒有被我們自定義的后置處理器增強的Bean么,我們可以看一下Spring共有多個Bean存在。

控制bean的兩種擴展方式

兩種方式可以對bean做控制(例如修改某個成員變量)
1. 改變bean的定義(BeanFactoryPostProcessor接口) ,可以想象成修改了class文件,這樣實例化出來的每個對象都變了;
2. 只改變實例化的對象(BeanPostProcessor接口);

源碼分析:BeanPostProcessor接口的實現類如何被注冊到spring容器

1. 從spring容器的初始化代碼看起吧,看AbstractApplicationContext類的refresh方法,如下圖所示,紅框中的方法負責將BeanPostProcessor接口的實現類注冊到spring容器:

2.?展開registerBeanPostProcessors方法,發現是委托PostProcessorRegistrationDelegate類的靜態方法registerBeanPostProcessors來完成注冊工作的:

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); }

3. 展開PostProcessorRegistrationDelegate.registerBeanPostProcessors方法,里面的代碼邏輯簡潔整齊,意圖目的一目了然:

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {//獲取所有實現BeanPostProcessor接口的bean的名稱String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);//注意,此時盡管注冊操作還沒有開始,但是之前已經有一些特殊的bean已經注冊進來了,//詳情請看AbstractApplicationContext類的prepareBeanFactory方法,//因此getBeanPostProcessorCount()方法返回的數量并不為零,//加一是因為方法末尾會注冊一個ApplicationListenerDetector接口的實現類int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;//這里的BeanPostProcessorChecker也是個BeanPostProcessor的實現類,用于每個bean的初始化完成后,做一些簡單的檢查beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));//如果這些bean還實現了PriorityOrdered接口(在意執行順序),就全部放入集合priorityOrderedPostProcessors List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();//集合internalPostProcessors,用來存放同時實現了PriorityOrdered和MergedBeanDefinitionPostProcessor接口的beanList<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();//集合orderedPostProcessorNames用來存放實現了Ordered接口的bean的名稱(在意執行順序)List<String> orderedPostProcessorNames = new ArrayList<String>();//集合nonOrderedPostProcessorNames用來存放即沒實現PriorityOrdered接口,也沒有實現Ordered接口的bean的名稱(不關心執行順序)List<String> nonOrderedPostProcessorNames = new ArrayList<String>();for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);//實現了PriorityOrdered接口的bean,都放入集合priorityOrderedPostProcessorspriorityOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {//實現了MergedBeanDefinitionPostProcessor接口的bean,都放入internalPostProcessors集合internalPostProcessors.add(pp);}}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {//實現了Ordered接口的bean,將其名稱都放入orderedPostProcessorNames集合orderedPostProcessorNames.add(ppName);}else {//既沒實現PriorityOrdered接口,也沒有實現Ordered接口的bean,將其名稱放入nonOrderedPostProcessorNames集合nonOrderedPostProcessorNames.add(ppName);}}//實現了PriorityOrdered接口的bean排序OrderComparator.sort(priorityOrderedPostProcessors);//注冊到容器registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();//處理所有實現了Ordered接口的beanfor (String ppName : orderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);orderedPostProcessors.add(pp);//前面將所有實現了PriorityOrdered和MergedBeanDefinitionPostProcessor的bean放入internalPostProcessors,//此處將所有實現了Ordered和MergedBeanDefinitionPostProcessor的bean放入internalPostProcessorsif (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}//實現了Ordered接口的bean排序OrderComparator.sort(orderedPostProcessors);//注冊到容器registerBeanPostProcessors(beanFactory, orderedPostProcessors);List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();for (String ppName : nonOrderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);nonOrderedPostProcessors.add(pp);//此處將其余實現了MergedBeanDefinitionPostProcessor的bean放入internalPostProcessorsif (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}//注冊到容器registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);OrderComparator.sort(internalPostProcessors);//將所有實現了MergedBeanDefinitionPostProcessor接口的bean也注冊到容器registerBeanPostProcessors(beanFactory, internalPostProcessors);//創建一個ApplicationListenerDetector對象并且注冊到容器,這就是前面計算beanProcessorTargetCount的值時加一的原因beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }

以上代碼已加注釋,就不多解讀了,有一點需要注意:對于實現了MergedBeanDefinitionPostProcessor接口的bean,在前面幾次調用registerBeanPostProcessors方法的時候已經注冊過了,那么在最后執行的registerBeanPostProcessors(beanFactory, internalPostProcessors),豈不是將一個bean注冊了多次?

為了弄清楚這個問題需要看registerBeanPostProcessors方法:

private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {for (BeanPostProcessor postProcessor : postProcessors) {//對每個bean都調用beanFactory.addBeanPostProcessor方法來注冊beanFactory.addBeanPostProcessor(postProcessor);} }

addBeanPostProcessor方法的代碼在AbstractApplicationContext類中,如下所示,先刪除再添加,這樣反復注冊也沒有問題

@Override public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");//如果已經注冊,就先刪除掉this.beanPostProcessors.remove(beanPostProcessor);//再注冊this.beanPostProcessors.add(beanPostProcessor);if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {this.hasInstantiationAwareBeanPostProcessors = true;}if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {this.hasDestructionAwareBeanPostProcessors = true;} }

至此,我們已經弄清楚了BeanPostProcessor實現類的bean注冊到spring容器的邏輯,接下來看看spring容器如何使用這些bean;

源碼分析,BeanPostProcessor實現類如何被使用

1.?要弄清楚BeanPostProcessor接口的實現類是在哪里被用到的,還是從負責容器初始化的AbstractApplicationContext類的refresh方法看起,如下圖紅框中的finishBeanFactoryInitialization方法,就是負責實例化和初始化bean的:

2.?從finishBeanFactoryInitialization方法到BeanPostProcessor的實現類被使用,中間有多層邏輯和調用,篇幅所限就不逐個展開了,直接列出堆棧信息,您可以根據此信息去查看對應源碼:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean() org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean() org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean() org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject() org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton() org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean() org.springframework.beans.factory.support.AbstractBeanFactory.getBean() org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons() org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization() org.springframework.context.support.AbstractApplicationContext.refresh() org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh() org.springframework.boot.SpringApplication.refresh() org.springframework.boot.SpringApplication.refreshContext() org.springframework.boot.SpringApplication.run() org.springframework.boot.SpringApplication.run() org.springframework.boot.SpringApplication.run()

3. 根據上述堆棧信息,直接查看AbstractAutowireCapableBeanFactory類的initializeBean()方法:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged(new PrivilegedAction<Object>() {@Overridepublic Object run() {invokeAwareMethods(beanName, bean);return null;}}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {//對已經實例化的bean,在初始化前用BeanPostProcessor實現類去處理wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {//bean的初始化invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {//對已經實例化的bean,在初始化后用BeanPostProcessor實現類去處理wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean; }

如上所示,我們最關注的代碼是applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization這兩個方法,它們分別在bean的初始化方法invokeInitMethods的前后被執行;

4. 先看看applyBeanPostProcessorsBeforeInitialization方法,邏輯非常簡單,就是取出所有已注冊的BeanPostProcessor實現類,執行其postProcessBeforeInitialization方法,入參是當前正在做實例化和初始化的bean實例:

@Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;//逐一執行每個BeanPostProcessor實現類的postProcessBeforeInitialization方法for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {result = beanProcessor.postProcessBeforeInitialization(result, beanName);if (result == null) {return result;}}return result; }

5. 在invokeInitMethods方法執行完畢后會執行applyBeanPostProcessorsAfterInitialization方法,代碼如下,與applyBeanPostProcessorsBeforeInitialization如出一轍,僅有的不同是調用的beanProcessor的方法變成了postProcessAfterInitialization:

@Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;//逐一執行每個BeanPostProcessor實現類的postProcessAfterInitialization方法for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {result = beanProcessor.postProcessAfterInitialization(result, beanName);if (result == null) {return result;}}return result; }

以上就是spring容器初始化過程中對BeanPostProcessor實現類的使用場景,此時還剩一點疑問需要澄清:在分析注冊過程的時候,曾看到實現MergedBeanDefinitionPostProcessor接口的bean是最后注冊的,那么這些MergedBeanDefinitionPostProcessor實現類在spring容器中是何處使用的呢?
為了搞清這個問題,來看看AbstractAutowireCapableBeanFactory類的doCreateBean方法,前面我們分析的initializeBean方法就是在這里面被調用的:

如上圖所示,紅框中就是用所有MergedBeanDefinitionPostProcessor實現類去處理當前正在實例化的bean,然后才會執行綠框中的initializeBean方法(里面是我們剛才分析的bean的初始化,BeanPostProcessor實現類被使用的邏輯);
來看看紅框中的applyMergedBeanDefinitionPostProcessors方法,主要目的是處理特殊的合成bean的定義類:

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)throws BeansException {try {//取出每個注冊的BeanPostProcessor實現類for (BeanPostProcessor bp : getBeanPostProcessors()) {//只有實現了MergedBeanDefinitionPostProcessor接口才執行if (bp instanceof MergedBeanDefinitionPostProcessor) {MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;//執行postProcessMergedBeanDefinitionbdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);}}}catch (Exception ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing failed of bean type [" + beanType + "] failed", ex);} }


至此,我們對BeanPostProcessor有關的源碼分析就完成了,小結一下:
1. 初始化時,spring容器有特別處理,會直接調用beanFactory.addBeanPostProcessor進行注冊(例如AbstractApplicationContext類的prepareBeanFactory方法中就有);
2. 找出所有實現了BeanPostProcessor接口的bean,注冊到容器,注冊順序如下:
第一:實現了PriorityOrdered接口的,排序后;
第二:實現了Ordered接口的,排序后;
第三:既沒實現PriorityOrdered接口,也沒有實現Ordered接口的;
第四:實現了MergedBeanDefinitionPostProcessor接口的(這些也按照PriorityOrdered、Ordered等邏輯拍過續);
第五:實例化一個ApplicationListenerDetector對象;
3. 實例化bean的時候,對于每個bean,先用MergedBeanDefinitionPostProcessor實現類的postProcessMergedBeanDefinition方法處理每個bean的定義類;
4. 再用BeanPostProcessor的postProcessBeforeInitialization方法處理每個bean實例;
5. bean實例初始化;
6. 用BeanPostProcessor的postProcessAfterInitialization方法處理每個bean實例;

源碼分析結束,接下來自定義一個BeanPostProcessor實現類,驗證我們之前的分析:控制bean實例;

?

總結

以上是生活随笔為你收集整理的Spring系列之BeanPostProcessor分析的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 天天色天天干天天色 | 成人h片在线观看 | 草逼视频网站 | 日韩无套无码精品 | 中文字幕天堂在线 | 欧美9999| 国产高潮又爽又无遮挡又免费 | 无码人妻一区二区三区精品视频 | 久人人| 日韩亚洲精品在线 | 香蕉av一区二区三区 | 国产三级精品三级在线 | 老女人网站 | 精品一区二区欧美 | 精品一区久久久 | 日本女优在线看 | 成人在线播放av | 少妇被按摩师摸高潮了 | 国产只有精品 | 国产福利观看 | 在线天堂在线 | 韩国电影大尺度在线观看 | 久久理论电影 | 亚洲天堂网一区 | 1024手机看片国产 | 咪咪色图| 精品国产乱码久久久久久免费 | 天天色影网 | 中文字幕色网 | 青青草手机在线观看 | 伊人9| 成人精品在线看 | 污视频网站免费观看 | 污的网站| 日韩视频中文 | 久久久久久久久久久久久久久 | 国产精品1页 | 日韩色小说 | 综合精品一区 | 九九热精品 | 性高跟鞋xxxxhd国产电影 | 神马九九| 久久久av片 | 97神马影院 | 日本一区二区不卡在线 | 成人h视频在线观看 | 一区二区三区免费在线观看视频 | 国产乱淫精品一区二区三区毛片 | 午夜激情综合 | 国产区福利| 999久久久国产精品 韩国精品一区二区 | 18禁裸男晨勃露j毛免费观看 | 清冷男神被c的合不拢腿男男 | 亚洲一区二区三区四区av | 国产第2页 | 国产精品久久无码 | 里番精品3d一二三区 | 国产成人av一区二区三区不卡 | 亚洲男人天堂2018 | 亚洲av不卡一区二区 | 日韩免费观看视频 | 成熟人妻av无码专区 | 日批黄色 | 西欧free性满足hd老熟妇 | 天堂岛av | 中文字幕免费在线 | 国产极品在线播放 | 公肉吊粗大爽色翁浪妇视频 | 国产视频你懂的 | 农村妇女一区二区 | 最近中文字幕在线观看 | 制服丝袜第一页在线观看 | 少妇免费毛片久久久久久久久 | 国产精品一区二区在线 | 亚洲综合中文字幕在线 | 国模av在线 | 欧美丰满bbw | 伊在线久久丫 | 天天人人精品 | 中文字幕在线高清 | 青青草视频在线观看免费 | 性色视频在线 | 男人懂的网站 | 国产操女人 | 日本人视频69式jzzij | 久久亚洲精品无码va白人极品 | 国产真人做爰毛片视频直播 | 久久久久国产精品 | 国产黄色免费观看 | 女女同性女同一区二区三区按摩 | 超碰99在线观看 | 91av免费在线观看 | 亚洲天天看 | 91豆花视频 | 亚洲乱码久久 | 成人一级毛片 | 欧美日韩91 | 朝桐光一区二区三区 | 极品少妇网站 |