1. 程式人生 > >【Spring4揭祕 BeanFactory】修改BeanFactory-BeanFactoryPostProcessor

【Spring4揭祕 BeanFactory】修改BeanFactory-BeanFactoryPostProcessor

一、BeanFactoryPostProcessor

當spring初始化好BenaDefinnitionMap之後,提供了一個介面BeanFactoryPostProcessor,允許我們開發者自定義的去修改BeanFactory中的內容,這也是符合“spring”的開閉原則

public interface BeanFactoryPostProcessor {

    /**
     * 這裡提供了修改beanFacotry的機會
         */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws
BeansException; }

BeanDefinitionRegistryPostProcessor繼承自BeanFactoryPostProcessor ,提供了更強大的功能。

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

    /**
     * 這個介面繼承了postprocessor 並且將beanFactory轉成了registry能夠訪問並修改BeanDefinition。
     */
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws
BeansException; }

二、自定義BeanFactoryPostProcessor

實現BeanFactoryPostProcessor介面即可

public class MyFactoryProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        //這裡可以呼叫ConfigurableListableBeanFactory方法對它處理
//... System.out.println("postProcessBeanFactory處理中...."); } }

手動呼叫BeanFactoryPostProcessor

public class Tester {
    public static void main(String[] args) throws Exception {

        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        new MyFactoryProcessor().postProcessBeanFactory(factory);


    }
}


==============輸出:============
postProcessBeanFactory處理中....

三、Spring常用BeanFactoryPostProcessor

spring也提供了不少BeanFactoryPostProcessor的實現,最常用的幾個:PropertySourcesPlaceholderConfigurer 、 CustomerEditorConfigurer、 PropertyOverrideConfigurer等。

3.1 佔位符處理器

這裡寫圖片描述
【PropertyPlaceholderConfigurer】可以從屬性檔案、屬性類獲取屬性
【PreferencesPlaceholderConfigurer】對屬性來源具有優先順序順序
【PropertySourcesPlaceholderConfigurer 】提供了比PropertyPlaceholderConfigurer更強大的功能,可以從屬性檔案、屬性類、環境、PropertySources等獲取屬性(Spring3.1以後推薦使用這個類)
【PropertyOverrideConfigurer】可以讀取帶有bean id的屬性直接向bean注入屬性,而不需要配置

PropertySourcesPlaceholderConfigurer

使用方法:

public class Tester {
    public static void main(String[] args) throws Exception {
        //建立一個BeanFactory,並註冊一個bean,bean的類名用佔位符表示
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        RootBeanDefinition beanDefinition = new RootBeanDefinition("${beanName}");//佔位符
        beanDefinition.setScope("${scop}");//佔位符
        factory.registerBeanDefinition("myBean", beanDefinition);

        //建立一個PropertySourcesPlaceholderConfigurer,
        //並加入含有佔位符字串對應的 MutablePropertySources
        PropertySourcesPlaceholderConfigurer configurer
                 = new PropertySourcesPlaceholderConfigurer();
        Map<String, Object> map = new HashMap<>();
        map.put("beanName", "Tester");//佔位符對應
        map.put("scop", RootBeanDefinition.SCOPE_PROTOTYPE);//佔位符對應“prototype”
        MutablePropertySources sources = new MutablePropertySources();
        sources.addLast(new MapPropertySource("abc", map));
        configurer.setPropertySources(sources);

        //對 BeanFactory增強,會替換掉佔位符
        configurer.postProcessBeanFactory(factory);

        //獲取這個bean
        System.out.println(factory.getBeanDefinition("myBean"));
        System.out.println(factory.getBean("myBean"));

    }

    @Override
    public String toString() {
        return "A bean";
    }
}

3.2 CustomerEditorConfigurer

java是強型別的一種語言:int,String,String[],Person等等等等。
而我們配置的xml,裡面都是字面量,也就是說,spring拿到的原始資料全部是字串。
那麼,spring是怎麼把字串轉成各種各樣的型別呢? 用 CustomEditorConfigurer,
Spring內部通過JavaBean的PropertyEditor來幫助進行String型別到其他型別的轉換工作。只要為每種物件型別提供一個PropertyEditor,就可以根據該物件型別取得與其相對應的PropertyEditor來做具體的型別轉換。Spring容器內部在做具體的型別轉換的時候,會採用JavaBean框架內預設的PropertyEditor搜尋邏輯。

3.3 ConfigurationClassPostProcessor

ConfigurationClassPostProcessor是一個BeanFactory和BeanDefinitionRegistry處理器,BeanDefinitionRegistry處理方法能處理@Configuration等註解。
通過檢視原始碼,ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry(..)內部使用ConfigurationClassParser類來處理@Configuration,@Import,@ImportResource和類內部的@Bean
如果@Import包含的Bean為ImportSelector型別。還會呼叫ImportSelector#selectImports()生成相應的Bean。
【ConfigurationClassPostProcessor基本使用】

class User{
   //示例類
}
@Configuration
@Import({User.class})
public class ConfigTest {

    @Bean
    Date date() {
        return new Date();
    }

    public static void main(String[] args) {
        ConfigurationClassPostProcessor postProcessor = new ConfigurationClassPostProcessor();
        SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
        registry.registerBeanDefinition("test", new RootBeanDefinition(ConfigTest.class));

        //處理BeanDefinitionRegistry
        postProcessor.postProcessBeanDefinitionRegistry(registry);
        //輸出結果
        System.out.println(registry.getBeanDefinition("test"));//可以輸出
        System.out.println(registry.getBeanDefinition("date"));//可以輸出
        System.out.println(registry.getBeanDefinition("User"));//可以輸出
    }
}

【ConfigurationClassPostProcessor配合@Import/ImportSelector使用】

class User{
     //示例類
}

class MySelector implements ImportSelector{
    //自定義一個ImportSelector實現類
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //會生成兩個Bean(java.util.Date和User)
        return new String[]{"java.util.Date","User"};
    }
}
@Configuration
@Import({MySelector.class})
public class ConfigTest { 
    public static void main(String[] args) {
        ConfigurationClassPostProcessor postProcessor = new ConfigurationClassPostProcessor();
        SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
        registry.registerBeanDefinition("test", new RootBeanDefinition(ConfigTest.class));

        postProcessor.postProcessBeanDefinitionRegistry(registry);

        System.out.println(registry.getBeanDefinition("test"));//
        System.out.println(registry.getBeanDefinition("User"));//可以輸出
        System.out.println(registry.getBeanDefinition("java.util.Date"));//可以輸出
     }
}

相關推薦

Spring4揭祕 BeanFactory修改BeanFactory-BeanFactoryPostProcessor

一、BeanFactoryPostProcessor 當spring初始化好BenaDefinnitionMap之後,提供了一個介面BeanFactoryPostProcessor,允許我們開發者自定義的去修改BeanFactory中的內容,這也是符合“spr

Spring4揭祕 基礎5BeanDefinition及讀取、註冊

一、 BeanDefinition及其實現類 BeanDefinition介面 這個介面描述bean的結構,對應XML中的< bean >或者配置類中的@Bean 它繼承了BeanMetadataElement和AttributeAccess

Spring原始碼分析11-BeanFactory

BeanFactory是Spring容器實現的基礎,訪問Spring容器的根介面。每個bean都是通過string型別bean name進行標識.這邊提供了設計模式單例,原型的替代實現。如果bean name配置為單例,應用內只會獲取到一個例項。如果配置為原型,那麼可以例項化

Spring4揭祕 基礎2PropertySource和Enviroment

一 、抽象類PropertySource及子類 PropertySource是一個抽象類,它包含一個source和一個name。source可以是map或其他,通常是一組鍵值對。 這個類結構簡化如下: public abstract class Pro

數據庫修改表結構

efault span 表名 mit ren 修改字段 修改表 ble unit 一、修改字段默認值 alter table 表名 drop constraint 約束名字 ------說明:刪除表的字段的原有約束 alter table 表名 add constra

Taro全實踐修改radio元件的大小

需求是將radio選中後顏色改為橙色、大小改成合適大小。 1、改顏色 <Radio color='#FF7464'></Radio> 2、改大小 <Radio style={{transform:'scale(0.8)'}} color='#FF74

python小操作修改文件任意位置的內容

Python基本文件操作 讀入文件: f = open(‘test.txt’,’r’) 寫入文件: F = open(‘output.txt’,’w’) 注意!如果你想讀文件,卻寫錯了關鍵字,把’r’寫成’w’,並運行了程式,那麼你的文件就會變成空白的,因為你什麼都

舊文章搬運修改PEB,斷鏈隱藏模組成功

原文發表於百度空間,2008-7-26========================================================================== 繼續實踐之前的想法,就是斷掉如下這個結構中的雙向連結串列: typedef struct _LDR_MODULE

.Net碼農修改WebBrowser控制元件的核心解決方案

首先說一下原理 當下很大瀏覽器他們都是用了IE的core, 這個core只提供HTML/JS的執行和渲染,並沒有給出關於介面和一些特性上的事,所以開發自己瀏覽器如果基於IE core需要自己完成這些內容。 一張圖很好的說明了這個情況,IE瀏覽器的架構:http://msdn.microsoft.com/e

Eclipse開發工具 修改 Web 專案的名稱(圖文案例)

開啟Eclipse 切換到  Navigator 檢視,能顯現出專案下所有的檔案便於修改 1、修改該專案目錄下:.project檔案 <projectDescription> <n

工作筆記0023修改已提交的 git comments 的作者資訊(Changing author info)

最近想把本地的程式碼庫上傳到github上,結果上傳完畢後才發現作者莫名其妙變成了其他人 追究原因,發現我用的 smartgit 工具,當初在配置 Comment 資訊時,填寫了正確的 username,但卻隨便填寫了一個 useremail為“[email p

Spring原始碼解讀BeanFactory和FactoryBean區別及類裝載原始碼解讀

最近讀程式碼讀到Bean裝載過程,順帶上網搜了下BeanFactory和FactoryBean,發現好多文章都講的不清不楚,特此自己來整理了一份BeanFactory和FactoryBean的區別及講下bean的裝載和讀取過程的原始碼.     首先來

Spring學習筆記1:開發環境,BeanFactory和ApplicationContext兩類容器

開發環境 和Struts2,Hibernate一樣把下載的jar包放在WEB-INF/lib/下就可以了,最小依賴是: 其中commons-logging-*.jar是額外的,不是Spring自帶的。 BeanFactory容器 是為依賴注入(DI)

Spring原始碼解析—— 簡單工廠模式的BeanFactory的超簡版實現

 一、什麼是簡單工廠模式 設計模式的核心是“分工”,通過分工將物件與職責劃分的更細化,進而提升系統設計的可擴充套件性,使其更容易維護。   開閉原則:對擴充套件開放,對修改關閉;要增加一個新的處理邏輯,可以開一個新的類,不要在老的上面修改 依賴倒轉原則:依賴關係從具體轉向抽象,也就是說:A

X-Forwarded-ForWEB修改訪客IP

識別 int urn 開發 user p地址 連接 通過 light X-Forwarded-For(XFF)是用來識別通過HTTP代理或負載均衡方式連接到Web服務器的客戶端最原始的IP地址的HTTP請求頭字段。 Squid 緩存代理服務器的開發人員最早引入了這一HTTP

Java修改jar包class文件小記

加密 返回 .cn 代碼 要求 ges 命令 文件 定位 今天被瑤瑤要求幫忙了 他現在用的軟件裏有一個bug,因為是外國的開發者,所以要求修改是很麻煩的事。要改的東西很簡單,就是將一個函數裏錯誤的返回值修改。 拿到手的有軟件直接能運行的jar包。 一開始的想法比較簡單,就想

第四組交互設計文檔 || 最後修改日期:07/29/17

文件夾 發送 bar box 新頁面 添加圖片 修改 反饋 com 一、圖庫頁面 1. 圖庫:點擊後會轉入頁面一(本頁) 2. 回憶:點擊後會轉入頁面九 3. 添加圖片來源:點擊後會轉入頁面二 4. 刷新:點擊後會刷新頁面一,停留在本頁(如果新圖片,新狀態見頁面七) 5.

SSH---Struts2、Hibernate5、Spring4散點知識

作用域 才會 進行 namespace sci 3.2 對象關系映射 工作 XML 一、Struts21.1、Struts2的概念Struts2是一個用來開發MVC應用程序的框架,它提供了Web應用程序開發過程中的一些常見問題的解決方案: ->對來自用戶的輸入數

代碼學習角色添加權限的方法,先刪除,再添加。而不是用修改,這樣很方便。

方便 添加權限 public resource res bject void @override != @Overridepublic void addRoleResources(Resources[] resources, Long roleId) { Map<

網站管理5_講解網站後臺SEO優化和如何修改關鍵字以及關鍵詞布局

日期 布局 指數 soft blog ros seo優化 優化 www 講解網站後臺SEO優化和如何修改關鍵字以及關鍵詞布局 制作:賴忠標 QQ:392277956 1.打開後臺點擊左側邊上的欄目,點擊最後的系統-系統基本參數-站點設置 如下圖