javascript
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的定義類:
至此,我們對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分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AnnotationConfigAppl
- 下一篇: Aware接口