當前位置:
首頁 > 知識 > Spring5源碼解析-Spring中的bean工廠後置處理器

Spring5源碼解析-Spring中的bean工廠後置處理器

Spring5源碼解析-Spring中的bean工廠後置處理器

Spring允許我們使用bean來進行大量的操作(這也是我們面向對象思想最常用的表達方式)。我們可以決定它們在容器中是否是(單例或者是原型)唯一實例。通過bean工廠後置處理器我們還可以在初始化時進行一些額外的操作。

在這篇文章中,來介紹下bean factory post processor。在第一部分,我們來發現下這個概念背後玄機。之後我們會寫一些有趣代碼來讓大夥更好地理解這個概念。

什麼是Spring工廠的後置處理器?

有時我們可能需要在Spring應用程序中實現一些動態行為。舉個簡單的例子,假設在你的網站中,你要顯示按時間來顯示兩個文本內容。上午的時候,你會顯示「早安」。下午,顯示的文字將是「下午好」。另外,你有兩個日常部署,上午12點,另一個在晚上12點。需要強調的是,這個文本內容必須由一個bean來處理。我們現在有兩個選擇:每次部署時更改應用程序上下文文件(太麻煩了),或者定義一個實現org.springframework.beans.factory.config.BeanFactoryPostProcessor介面的bean 。第二個解決方案更優雅,因為我們只需要編寫一次代碼,然後就可以忽視它的存在了(無須次次去修改了)。

那麼,這個優雅的BeanFactoryPostProcessor是何方神聖?它是由bean實現的介面,它們可以修改其他bean的定義。請注意,只能修改定義,即構造函數參數,屬性值。BeanFactoryPostProcessorbean在初始化「正常」bean之前被調用,這就是為什麼它能修改元數據的原因(meta data)。調用是通過org.springframework.context.support.AbstractApplicationContext的 protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)來實現的:

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());}

在PostProcessorRegistrationDelegate裡面,負責bean factory後置處理器執行的方法是:

/** * Invoke the given BeanFactoryPostProcessor beans. */private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}}

如你所見,由BeanFactoryPostProcessor實現覆蓋的主要方法是postProcessBeanFactory。這也是我們來自己定製bean定義的地方。我們通過在org.springframework.beans.factory.config.BeanDefinition對象上進行定製。關於這點我已經在Spring5源碼解析-Spring框架中的單例和原型bean的文章中已經寫過,它們(BeanDefinition對象)包含大量關於bean元數據的信息:構造函數參數,屬性值或作用域。

一個簡單的Spring bean廠後置處理器Demo

關於理論的重要部分已經都在前面進行了描述。在這部分中,我們將重點放在一個簡單實用的案例上。你還記得第一部分的「早安」和「下午好」的例子?如果忘了,請回去再瞅眼的。接著,讓我們嘗試在代碼中實現這種案例。首先,我們將在配置文件中定義一些bean:

<bean class="com.migo.bean.BeanModifier">
<bean name="welcomerBean" class="com.migo.bean.Welcomer" init-method="initWelcomer">
<property name="welcomeText" value="Good morning"></property>
</bean></bean>

第一個bean代表將實現BeanFactoryPostProcessor介面的bean。第二個bean是注入的類,它會在頁面中顯示歡迎的文本內容。他們是兩個bean的代碼:

// Welcomer.javapublic class Welcomer {
private String welcomeText;
public void initWelcomer() {
LOGGER.debug("Welcomer is initialized");
}
public void setWelcomeText(String welcomeText) {
LOGGER.debug("Setting welcomeText to: "+welcomeText);
this.welcomeText = welcomeText;
}
public String getWelcomeText() {
return this.welcomeText;
}
@Override
public String toString() {
return "Welcomer {text: "+this.welcomeText+"}";
}
}
// BeanModifier.javapublic class BeanModifier implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
try {
Calendar calendar = Calendar.getInstance();
if (calendar.get(Calendar.AM_PM) == Calendar.PM) {
BeanDefinition welcomerDef = beanFactory.getBeanDefinition("welcomerBean");
welcomerDef.getPropertyValues().add("welcomeText", "Good afternoon");
}
} catch (Exception e) {
LOGGER.error("An error occurred on setting welcomeText", e);
}
}}
// test methodApplicationContext context = new FileSystemXmlApplicationContext("/home/bartosz/webapp/src/main/resources/META-INF/applicationContext.xml");
Welcomer welcomer = (Welcomer) context.getBean("welcomer");System.out.println("Text: "+welcomer.getWelcomeText());

如果現在是下午,輸出應該是:

Setting welcomeText to: Good afternoonWelcomer is initializedText: Good afternoon

我們可以看到,BeanModifier在Welcomer的真正初始化之前被調用。由於重寫覆蓋了postProcessBeanFactory方法,這樣我們可以通過檢查日期,並為屬性welcomeText設置正確的值。

這篇文章雖短,但它描述了一些在一些「動態」場景中我們如何以一個更效率的方式來實現的實用操作。比如,你會碰到這種,我們常常見到一個遊戲會有例行維護,那麼我們會發現排行榜會在例行維護後刷新,你每次登錄遊戲也會對你的一些屬性或者積分進行刷新,其實你每次登錄就是又初始化了一遍你這個bean,這樣,我們就可以做很多事情了,比如為最佳用戶添加一些獎勵積分。通過BeanFactoryPostProcessor這個 bean,這種處理就可以在Java方法內自動完成,無須我們在每次部署時通過手動來完成。


原文:Spring5源碼解析-Spring中的bean工廠後置處理器

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 青峰科技 的精彩文章:

C++—const volatile mutable的用法
騰訊雲DevOps流水線的應用與實踐
前方高能提示:SDCC 2017之區塊鏈技術實戰線上峰會開播倒計時
html 使用 gka 加速 createjs 動畫開發及圖片優化
Chrome 搜索 User-Agent Switcher 排行第一的插件竟是木馬

TAG:青峰科技 |