<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
BeanPostProcessor對於Spring開發者來說一定不陌生,平時開發過程中如果涉及對中介軟體做增強處理或者需要對某個實際Bean做初始化前的處理,一般都可以使用該介面來實現。
對於自己來說自己在對接RocketMQ、RabbitMQ過程中需要實現一個快速接入SpringBoot的中間外掛,最快速的就是實現該介面對中介軟體中的Bean做增強處理,能夠快速接入SpringBoot。
BeanPostProcessor是一個介面,該介面提供給開發者使用,開發者可以實現該介面,然後在實現類中對想要處理的類做增強處理。
該介面中提供了兩個基礎方法:
public interface BeanPostProcessor { @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
下面舉一個最簡單的例子來看一下BeanPostProcessor的使用。
@Service public class UserService { private String name = "陳tom"; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
@Component public class MyPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if ("userService".equals(beanName)) { UserService userService = (UserService) bean; userService.setName("陳湯姆"); userService.setAge(21); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); } }
@SpringBootApplication public class BootApplication { @Resource private DefaultListableBeanFactory defaultListableBeanFactory; public static void main(String[] args) { SpringApplication.run(BootApplication.class,args); } @PostConstruct public void init() { UserService userService = defaultListableBeanFactory.getBean("userService", UserService.class); System.out.println("測試結果:姓名:"+userService.getName()+";年齡:"+userService.getAge()); } }
以上的實現中做了最簡單的實現,通過MyPostProcessor實現BeanPostProcessor介面,然後在前置增強處理中加入對Bean的修改。
然後通過PostConstruct在Bean初始化後做Bean的查詢,得到通過BeanPostProcessor操作的結果。
所以BeanPostProcessor在使用上來說很簡單,對於開發者來說它很方便的提供了對於Bean物件的修改操作,提高了Spring的擴充套件性和靈活性。
說完了最基礎的BeanPostProcessor的使用,通過以上的實現來梳理下BeanPostProcessor的作用。
自己對於BeanPostProcessor最大的感受就是太靈活了,開發者只要實現該介面,然後重寫其中的方法就可以實現自己的邏輯。這樣也保證了Spring容器對於開發者來說並不是一個黑盒,開發者可以通過Spring提供的鑰匙讓Spring容器暴露在開發者眼中,想要做什麼處理都可以根據提供的鑰匙實現。(這裡其實還有一個配套的BeanFactoryPostProcessor,面試的時候也經常被問到BeanPostProcessor和BeanFactoryPostProcessor的區別,有興趣的可以自己瞭解下,區別只是最終服務的物件不一樣)
這裡不得不說Spring YYDS!!!
Q:既然開發者通過自己的實現類實現了BeanPostProcessor,那麼Spring又是如何將開發者做的實現類加入到Spring中並且執行開發者重寫的前置和後置增強邏輯呢?
這裡就要提到Spring對於BeanPostProcessor的設計,在Spring中初始化了一個CopyOnWriteArrayList作為儲存所有實現BeanPostProcessor的列表。
從實現上可以看到該列表是一個寫複製的列表,通俗點講就是向該列表中新增元素時,不直接往當前容器新增,而是先將當前容器進行Copy,複製出一個新的容器,然後新的容器裡新增元素,新增完元素之後,再將原容器的參照指向新的容器。這裡不展開說只要知道就是一個列表就可以。
Spring向該容器中新增的邏輯原始碼如下:
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { //儲存BeanPostProcessor列表 private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>(); @Override public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null"); // Remove from old position, if any this.beanPostProcessors.remove(beanPostProcessor); // Track whether it is instantiation/destruction aware if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { this.hasInstantiationAwareBeanPostProcessors = true; } if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) { this.hasDestructionAwareBeanPostProcessors = true; } // 將BeanPostProcessor加入beanPostProcessors列表中 this.beanPostProcessors.add(beanPostProcessor); } }
這裡展示的只是最終寫入的邏輯,那麼從源頭到寫入BeanPostProcessor的邏輯是怎麼樣呢?
以ClassPatchXmlApplicationContext為例:
時序圖如下:
說完如何註冊BeanPostProcessor,最後來說如何將註冊到beanPostProcessors的實現類進行呼叫。
前一篇聊Spring容器時也提到了Spring在初始化Bean時會執行BeanPostProcessor的增強處理,具體的呼叫原始碼如下:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { //初始化Bean protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //呼叫BeanPostProcesso#postProcessBeforeInitialization:前置處理 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //執行初始化方法 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()) { //呼叫呼叫BeanPostProcesso#postProcessAfterInitialization:後置處理 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } //BeanPostProcessor前置邏輯處理 @Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { //執行實現BeanPostProcessor的實現類的前置增強邏輯 Object current = processor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; } //BeanPostProcessor後置邏輯處理 @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { //執行實現BeanPostProcessor的實現類的後置增強邏輯 Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; } }
從以上原始碼中可以看到在初始化Bean時呼叫前置和後置增強,並且這裡也做了明確的邊界,前置增強處理一定是在invokeInitMethods之前,後置增強一定是在invokeInitMethods之後。這樣就保證了BeanPostProcessor的執行順序,也可以讓開發者在使用過程中只要掌握Bean的生命週期,那麼就可以自主的對Bean進行增強處理。
以上是對Spring中BeanPostProcessor的原始碼梳理,對BeanPostProcessor的介紹到使用、作用、註冊實現和呼叫實現,完成了對BeanPostProcessor的原始碼分析。
對於文中提到的BeanFactoryPostProcessor有興趣的可以從原始碼按照這個過程梳理一下,其實跟BeanPostProcessor作用是相同的。
以上就是Spring BeanPostProcessor原始碼範例解析的詳細內容,更多關於Spring BeanPostProcessor的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45