spring步步前行(IOC)-強擼BeanFactoryPostProcessor

spring步步前行(IOC)-強擼BeanFactoryPostProcessor

spring爲我們提供的一些由我們自由控制時機的方式除了BeanPostProcessor外,還有一個叫BeanFactoryPostProcessor,我們知道BeanFactoryPostProcessor其作用是允許我們在工廠內所有的bean沒被初始化之前且在加載後,對所有bean的屬性進行修改,相信很多朋友對其作用和意義也是停留在看看,這一篇我們繼續使用一些實例輔助我們理解BeanFactoryPostProcessor

官方解讀

在這裏插入圖片描述

這個接口是允許修改應用上下文中的bean definitions來適配bean的屬性值,其也就是說spring在初始化beanDefinitionMap後爲我們提供了一個允許我們修改beanDefinition內容的契機

感覺和上一篇我們分析的beanPostProcessor很相像,我們再回頭將beanPostProcessor的官方註釋結合起來看看beanPostProcessor與beanFactoryPostProcessor有什麼不同

首先beanPostProcessor

Factory hook that allows for custom modification of new bean instances,
e.g. checking for marker interfaces or wrapping them with proxies.
允許修改新的bean的實例  

而beanFactoryPostProcessor官方是這樣描述的

A BeanFactoryPostProcessor may interact with and modify bean
definitions, but never bean instances. 
即beanFactoryPostProcessor是修改deanDefinitions而不是修改實例

從這裏我們很清晰的能看出它們倆的不同,beanFactoryPostProcessor修改的是beanDefinition,而beanPostProcessor修改的是bean的實例。那bean的實例與beanDefiniton的關係又是什麼呢?從之前的beanFactory的分析,我們瞭解到beanDefinition是對bean的描述,舉個例子也就是說一個公司打印海報,發現海報上的公司信息有問題,beanPostProcessor的做法就是直接劃掉換上新的,而beanFactoryPostProcessor的做法就是直接重新做一份海報,到這beanFactoryPostProcessor與beanPostProcessor的區別就很明顯了,beanFactoryPostProcessor完全修改屬性,而beanPostProcessor更像臨時修改bean的屬性

這裏我們簡單回顧下beanDefinition:

在這裏插入圖片描述

beanDefinition是對bean實例的描述,包括是否單例,是否抽象,是否懶加載屬性,構造參數等信息,其通過繼承AttributeAccessor賦予了其具備操作屬性相關的方法,繼承BeanMetadataElement來持有bean元數據元素的持有,總的來說就是將bean的信息存儲到這個BeanDefinition相應的屬性中,可根據其信息來反射創建對象

接下來我們看看beanFactoryPostProcessor的接口方法:

在這裏插入圖片描述

既然beanFactoryPostProcessor修改的是beanDefinition,而我們的beanDefinition又存儲在beanFactory內,那麼自然我們要方法上就需要beanFactory作爲參數了

實例

既然和beanPostProcessor很相近,那我們繼續沿用之前的demo好了,對於在beanPostProcessor的我們添加默認值的做法,可能有很多朋友對註解處理覺得不夠優雅,這一次我們改用beanFactoryPostProcessor來實現達到同樣的效果

首先對我們創建的調試bean做調整:

//去掉默認值的註解不在需要,注意提供set方法不然會報錯
public class ClazzBean {

//    @SetDefaultValue(defaultValue = "章三")
    public String name;
    public String clazz;
    public String extral;

//    @SetDefaultValue(defaultValue = "17213213")
    public String phone;

    public void setName(String name) {
        this.name = name;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    public void setExtral(String extral) {
        this.extral = extral;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "ClazzBean{" +
                "name='" + name + '\'' +
                ", clazz='" + clazz + '\'' +
                ", extral='" + extral + '\'' +
                ", phone='" + phone + '\'' +
                '}';
    }
}
		@Bean("clazzbean")//添加標記 後續通過clazzbean來獲取beanDefinition
    public ClazzBean test() {
        return new ClazzBean();
    }

然後對之前的BeanPostProcessor的postProcessBeforeInitialization內處理註解方法註釋不在需要

接着我們創建一個實現了BeanFactoryPostProcessor的Processor類,如下:

在這裏插入圖片描述

我們的改造就完畢了,跑起來爽一下看看效果:

在這裏插入圖片描述

果然達到同樣的效果,是不是優雅很多,一個字,爽!!

官例介紹

上一次我們舉例了spring中爲我們提供了很多我們可以學習的實例,畢竟耳聽爲虛,眼見爲實,這一次我們通過官方的一個beanFactoryPostProcessor的實現來眼見爲實一次

我們以一個過時警告的應用舉例子:

來自於org.springframework.beans.factory.config的DeprecatedBeanWarner,其作用是通過Deprecated註解來過濾警告我們有些類已經過期了,請注意

我們看看其實現:

在這裏插入圖片描述

首先Deprecated的功能簡單,很容易一目瞭然,主要是postProcessBeanFactory和logDeprecatedBean這兩個方法

在這裏插入圖片描述

首先先檢查log是否啓用,如果啓用,那麼通過beanFactory獲取所有beanDefinitionNames,然後遍歷,這裏注意isFactoryBean這個方法如果是factoryBean的話,需要通過"&"+beanName的方法查找class(對於factorybean我們會再找一篇機會重點分析一下,畢竟是spring ioc幾個關鍵組成),找到class後,看是否有Deprecated這個註解,如果有的話那麼就進入logDeprecatedBean方法

在這裏插入圖片描述
這個方法就更簡單了,將bean的信息打印出來,這樣就完成了警告

以上就是spring內部對beanFactoryPostProcessor的簡單應用,至此我們對beanFactory相信已經有了很深的印象,步步前行,紮實基礎!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章