深入理解Spring 之 Spring 進階開發必知必會 之 Spring 擴充套件介面
# 前言
我們在前幾篇文章中已經深入瞭解了 Spring 的 IOC 機制和 AOP 機制,在閱讀原始碼的同時,樓主對 Spring 中設計模式的運用可以說五體投地,還有我們還知道更重要的一點就是:Spring 留給了我們大量的擴充套件介面供開發者去自定義自己的功能,甚至於 AOP 就是在 Spring 預留的擴充套件介面中實現的,意思是隻要基於 Spring IOC,遵守 Spring 對擴充套件介面的約定,那麼就能實現自己想要的功能。可見 IOC 的強大,那麼。今天我們就將 Spring 留給我們的介面拿出來說一說。而我們的標題是Spring 進階開發,為什麼這麼說,如果說只是簡單的使用 Spring 中的bean,那麼只是Spring的初級開發者。如何精通Spring 就看有沒有掌握好Spring留給我們的這些擴充套件介面,以及如何使用他們。
我們今天主要講述以下幾個介面,如有遺漏,請指出:
- FactroyBean 我們熟悉的AOP基礎bean
- BeanPostProcess 在每個bena初始化成前後做操作。
- InstantiationAwareBeanPostProcessor 在Bean例項化前後做一些操作。
- BeanNameAware、ApplicationContextAware 和 BeanFactoryAware 針對bean工廠,可以獲取上下文,可以獲取當前bena的id。
- BeanFactoryPostProcessor Spring允許在Bean建立之前,讀取Bean的元屬性,並根據自己的需求對元屬性進行改變,比如將Bean的scope從singleton改變為prototype。
- InitialingBean 在屬性設定完畢後做一些自定義操作 DisposableBean 在關閉容器前做一些操作。
1. FactroyBean 我們熟悉的AOP基礎bean
這個Bean 我們再屬性不過,我們再學習 AOP 的時候,知道 XML 方式的 AOP 就是通過該介面實現的。我們複習以下該介面的結構。
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
該介面定義了3個方法,獲取bean例項,獲取bean型別,是否是單例。Spring 在 IOC 初始化的時候,一般的Bean都是直接呼叫構造方法,而如果該Bean實現了FactoryBean 介面,則會呼叫該Bean的 getObject 方法獲取bean,這也是Spring 使用此介面構造AOP的原因。在 IOC 呼叫此方法的時候,返回一個代理,完成AOP代理的建立。
我們做個測試:定義一個FactoryBean,重寫他的 getObject 方法:
測試類中呼叫:
注意:此時返回的已經是 AOP 型別的Bean,因為我們在 getObject 返回到是 new Aop(),驗證了我們之前說的。使用該介面,能夠為我們做很多有趣的事情。就靠你來想象了。
2. BeanPostProcess 在每個bean初始化成前後做操作。
該介面我們應該也非常的熟悉,還記的我們的註解配置的AOP是如何實現的。就是間接實現了該介面。在 IOC 初始化的時候,會呼叫的該介面的後置處理方法。我們看看該介面定義:
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
一個是前置方法,一個是後置方法,註解方式的AOP的實現就是在 postProcessAfterInitialization 方法中實現的。我們寫一個測試類,看看結果是什麼?
我們在Bean 初始化之前後之後都列印以下該Bean的名稱,那麼執行結果是什麼呢?下面是SpringBoot 啟動後的一部分日誌:
可以看到我們專案中所有的Bean在初始化的時候都呼叫該方法。因此,我們在以後的開發中就可以做一些自定義的事情。
3. InstantiationAwareBeanPostProcessor 在Bean例項化前後做一些操作。
這個介面實際上我們也是非常的熟悉,該介面在我們剖析註解配置AOP的時候是我們的老朋友,實際上,註解配置的AOP是間接實現 BeanPostProcess 介面的,而 InstantiationAwareBeanPostProcessor 就是繼承該介面的。我們看看他的繼承圖譜:
可以看到該介面在繼承的基礎上又增加了3個方法,增加了擴充套件bean的功能。我們寫個 Demo 測試一下:
可以看到,需要實現 5 個方法,其中2個方法是 BeanPostProcess 介面定義的方法:在bean初始化的前後執行,而 InstantiationAwareBeanPostProcessor 則新增了 3 個方法,分別是 postProcessBeforeInstantiation (例項化之前),postProcessAfterInstantiation (例項化之後),postProcessPropertyValues (在處理Bean屬性之前),開發者可以在這三個方法中新增自定義邏輯,比如AOP。我們看看執行結果。
可以看到,所有的Bean在IOC的時候都執行了我們的方法,其中例項化在初始化之前執行,這個順序對我們使用該介面是很重要的,千萬不要弄混。
4. BeanNameAware、ApplicationContextAware 和 BeanFactoryAware 針對bean工廠,可以獲取上下文,可以獲取當前bena的id。
這三個介面的功能其中都一樣,我們看看他們的繼承圖譜就知道了:
可以看到,這三個介面都繼承自 Aware 介面,並分別定義了自己的介面定義方法。實現這些介面就能得到Spring的Bean 工廠。從而呼叫getBean方法獲取Bean。很多專案中都使用此介面做了Spring的工具類。比如可以像這麼使用:
我們寫了一個測試類,然後看以下執行結果:
執行結果:
可以看到,在IOC的過程中,該Bean的三個方法都被執行,我們就可以獲取到容器,從而可以做很多自定義的額事情。
5. BeanFactoryPostProcessor Spring允許在Bean建立之前,讀取Bean的元屬性,並根據自己的需求對元屬性進行改變,比如將Bean的scope從singleton改變為prototype。
我們看看該介面的定義:
只定義了一個方法,該方法註釋:在它的標準初始化之後修改應用程式上下文的內部bean工廠。所有的bean定義都已經載入了,但是還沒有例項化bean。這允許覆蓋或新增屬性,甚至是對初始化bean的屬性。引數是什麼呢?應用程式上下文所使用的bean工廠。也就是說,我們可以獲取某個Bean的定義,然後修改該Bean的定義:比如下面這樣:
我們看看執行結果:
我們將成功的單例的Bean改成了多例。
6. InitialingBean 在屬性設定完畢後做一些自定義操作。 DisposableBean 在關閉容器前做一些操作。
我們寫以下demo 看看是如何執行的:
實現這兩個介面:
啟動類:
在執行啟動類之後,就會關閉容器。退出虛擬機器,我們看看執行結果:
在執行Set 屬性方法後,立即執行 afterPropertiesSet 方法,因此,我們就可以在該方法中做一些事情,然後在執行 System.exit(0) 後,執行 destroy 方法,我們也可以在該方法中執行一些邏輯。
7 總結
我們瞭解了 Spring 留給我們的擴充套件介面,以提高我們使用 Spring 的水平,在以後的業務中,也就可以基於 Spring 做一些除了簡單的注入這種基本功能之外的功能。同時,我們也發現,Spring 的擴充套件性非常的高,符合設計模式中的開閉原則,對修改關閉,對擴充套件開放,實現這些的基礎就是 Spring 的 IOC,IOC 可以說是 Spring 的核心, 在 IOC 的過程中,對預定義的介面做了很多的預留工作。這讓其他框架與 Spring 的組合變得更加的簡單,我們在以後的開發工作中也可以借鑑 Spring 的思想,讓程式更加的優美。
相關文章
- 深入理解Spring IOC容器及擴充套件Spring套件
- Spring擴充套件介面(2):BeanDefinitionRegistryPostProcessorSpring套件Bean
- 譯 - Spring 核心技術之 Spring 容器擴充套件點Spring套件
- Spring擴充套件介面(4):InstantiationAwareBeanPostProcessorSpring套件Bean
- spring4.1.8擴充套件實戰之四:感知spring容器變化(SmartLifecycle介面)Spring套件
- spring4.1.8擴充套件實戰之七:控制bean(BeanPostProcessor介面)Spring套件Bean
- 深入理解Spring原始碼之IOC 擴充套件原理BeanFactoryPostProcessor和事件監聽ApplicationListenerSpring原始碼套件Bean事件APP
- Spring 8:一些常用的 Spring Bean 擴充套件介面SpringBean套件
- iStylePDF介面物件必知必會系列之Page物件
- Android NDK 開發之 CMake 必知必會Android
- 學習SpringMVC必知必會(2)~走近Spring MVCSpringMVC
- ElasticSearch必知必會-進階篇Elasticsearch
- 學習Spring5必知必會(1)~未使用spring前的麻煩Spring
- Spring8:一些常用的Spring Bean擴充套件介面SpringBean套件
- 精選Spring Boot三十五道必知必會知識點!Spring Boot
- spring bean 擴充套件方式SpringBean套件
- 擴充套件、接管MVC都不會,還會用Spring Boot?套件MVCSpring Boot
- Redis 必知必會之 APIRedisAPI
- Java必知必會之socketJava
- spring4.1.8擴充套件實戰之八:Import註解Spring套件Import
- Spring IoC 容器的擴充套件Spring套件
- Spring容器擴充套件機制Spring套件
- 使用Spring Session實現Spring Boot水平擴充套件SessionSpring Boot套件
- Spring(11) - Introductions進行類擴充套件方法Spring套件
- spring4.1.8擴充套件實戰之五:改變bean的定義(BeanFactoryPostProcessor介面)Spring套件Bean
- Redis 必知必會之持久化Redis持久化
- Java必知必會之註解Java
- Spring原始碼之容器的功能擴充套件和refresh方法解析Spring原始碼套件
- spring4.1.8擴充套件實戰之六:註冊bean(BeanDefinitionRegistryPostProcessor)Spring套件Bean
- 使用Kotlin擴充套件函式擴充套件Spring Data案例Kotlin套件函式Spring
- 【java工程師必知必會】spring防重複提交AOP方式Java工程師Spring
- Spring擴充套件之二:ApplicationListenerSpring套件APP
- 擴充spring元件之自定義標籤Spring元件
- Spring之藉助Redis設計訪問計數器之擴充套件篇SpringRedis套件
- Spring系列-XML schema擴充套件機制SpringXML套件
- 聊聊spring的那些擴充套件機制Spring套件
- 聊聊Spring擴充套件點BeanPostProcessor和BeanFactoryPostProcessorSpring套件Bean
- 深入理解微服務架構spring的各個知識點(面試必問知識點)微服務架構Spring面試