一文看懂 Spring Aware 接口功能
前言
有些情況下,當(dāng)Bean需要實(shí)現(xiàn)某個(gè)功能時(shí),需要借助于 Spring容器對象屬性
才能實(shí)現(xiàn)。此時(shí)就需要讓該Bean先獲取Spring容器對象屬性,然后借助于Spring容器對象屬性實(shí)現(xiàn)該功能。
- 為了讓Bean獲取它所在的Spring容器對象屬性,可以讓該Bean實(shí)現(xiàn) 如ApplicationContextAware接口。
- 通過實(shí)現(xiàn)ApplicationContextAware接口并重寫set方法,Spring容器會(huì)自動(dòng)把上下文環(huán)境對象調(diào)用ApplicationContextAware接口中的setApplicationContext方法,然后就可以通過ApplicationContext對象得到Spring容器中的Bean。
- 可以將Aware理解為屬性注入,不過不同地方在于,只有實(shí)現(xiàn)了這個(gè)接口的bean,當(dāng)spring容器初始化的時(shí)候才會(huì)自動(dòng)的將ApplicationContext注入進(jìn)來。
Aware
Aware接口是一個(gè)空接口,可以理解為是一個(gè)標(biāo)記接口,方便在一個(gè)統(tǒng)一的方法(AbstractAutowireCapableBeanFactory.invokeAwareMethods)中進(jìn)行判斷處理賦值,在子接口寫出各自的set方法。
**Aware接口方法的主要作用是讓 Bean 能夠獲取 Spring 容器的相關(guān)資源和信息,以便在后續(xù)的初始化和業(yè)務(wù)邏輯中使用。**可以理解為之前的屬性賦值是將我們自定義屬性的值進(jìn)行賦值,而使用Aware可以讓我們拿到Spring容器內(nèi)部的容器對象。
/* * A marker superinterface * 在該接口的注釋中也解釋了該接口是一個(gè)標(biāo)記接口 */ public interface Aware { }
常見的 Aware 接口及功能
BeanNameAware接口
- 當(dāng)一個(gè) Bean 實(shí)現(xiàn)了BeanNameAware接口時(shí),它可以獲取自己在 Spring 容器中的 Bean 名稱。這個(gè)接口中只有一個(gè)方法setBeanName(String name),Spring 容器在創(chuàng)建 Bean 的過程中會(huì)調(diào)用這個(gè)方法,并將 Bean 的名稱作為參數(shù)傳遞進(jìn)去。
ApplicationContextAware接口
- 實(shí)現(xiàn)這個(gè)接口的 Bean 可以獲取 Spring 的應(yīng)用上下文(ApplicationContext)對象。ApplicationContext是 Spring 容器的核心接口,它提供了對容器中所有 Bean 的訪問權(quán)限,還包括獲取資源、發(fā)布事件等多種功能。
BeanFactoryAware接口
- 與ApplicationContextAware類似,實(shí)現(xiàn)BeanFactoryAware接口的 Bean 可以獲取 Bean 工廠(BeanFactory)對象。BeanFactory是 Spring 容器中用于創(chuàng)建和管理 Bean 的基礎(chǔ)接口,相對ApplicationContext來說更加輕量級。
ApplicationEventPublisherAware接口
- 如果Bean需要發(fā)布應(yīng)用事件,可以實(shí)現(xiàn)此接口。
ResourceLoaderAware接口
- 如果Bean需要加載資源文件(如XML文件、屬性文件等),可以實(shí)現(xiàn)此接口。
EnvironmentAware接口
- 如果Bean需要訪問環(huán)境特定的信息(如配置文件位置、激活的配置文件等),可以實(shí)現(xiàn)此接口。
MessageSourceAware接口
- 如果Bean需要進(jìn)行國際化處理,可以實(shí)現(xiàn)此接口以獲取消息源。
代碼示例
如:Bean 實(shí)現(xiàn)了 ApplicationContextAware 接口,此時(shí)Spring會(huì)通過 setApplicationContext() 給Bean中的ApplicationContext屬性值賦值。
org.springframework.context.ApplicationContextAware
public interface ApplicationContextAware extends Aware { void setApplicationContext(ApplicationContext applicationContext) throws BeansException; }
通過類實(shí)現(xiàn)ApplicationContextAware接口,并重寫接口中的setApplicationContext()方法,則可以獲取 Spring 的應(yīng)用上下文ApplicationContext對象
public class SpringContextUtil implements ApplicationContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public ApplicationContext getApplicationContext() { return applicationContext; } }
Aware 接口中set()的調(diào)用時(shí)機(jī)
在以上代碼中setApplicationContext()方法是spring容器進(jìn)行調(diào)用的,在invokeAwareMethods中統(tǒng)一調(diào)用。
當(dāng)子實(shí)現(xiàn)類實(shí)現(xiàn)ApplicationContextAware接口后,當(dāng)前類中重寫setApplicationContext為接口中setApplicationContext方法。Spring會(huì)在執(zhí)行invokeAwareMethods()時(shí)由容器進(jìn)行賦值。
Spring源碼中的具體實(shí)現(xiàn)如下:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
private void invokeAwareMethods(String beanName, Object bean) { //如果 bean 是 Aware 實(shí)例 if (bean instanceof Aware) { //如果bean是BeanNameAware實(shí)例 if (bean instanceof BeanNameAware) { //調(diào)用 bean 的setBeanName方法 ((BeanNameAware) bean).setBeanName(beanName); } //如果bean是 BeanClassLoaderAware 實(shí)例 if (bean instanceof BeanClassLoaderAware) { //獲取此工廠的類加載器以加載Bean類(即使無法使用系統(tǒng)classLoader,也只能為null) ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { //調(diào)用 bean 的 setBeanClassLoader 方法 ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } //檢查bean是否實(shí)現(xiàn)了BeanFactoryAware,如果是,則調(diào)用其setBeanFactory方法設(shè)置工廠實(shí)例。 if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
什么時(shí)候調(diào)用invokeAwareMethods方法
invokeAwareMethods()通常是在Spring容器初始化一個(gè)bean的過程中被調(diào)用的。
- 具體來說,在bean被創(chuàng)建并配置完成后,但還未完全初始化之前(即在init-method或InitializingBean的afterPropertiesSet()方法調(diào)用之前),Spring框架會(huì)檢查該bean是否實(shí)現(xiàn)了某些特定的接口,如BeanNameAware、BeanFactoryAware等,并相應(yīng)地調(diào)用這些接口的方法來設(shè)置必要的屬性。
- 這個(gè)過程是Spring框架內(nèi)部的一部分,用來確保bean能夠獲得一些關(guān)于自身或者Spring應(yīng)用上下文的信息。
- 例如,讓bean知道自己的名字、所屬的BeanFactory或者是類加載器等。這樣可以在bean的生命周期早期給予bean更多的上下文信息。
到此這篇關(guān)于一文看懂 Spring Aware 接口的文章就介紹到這了,更多相關(guān)Spring Aware 接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring MVC+MyBatis+MySQL實(shí)現(xiàn)分頁功能實(shí)例
分頁功能是我們?nèi)粘i_發(fā)中經(jīng)常會(huì)遇到的,下面這篇文章主要給大家介紹了Spring MVC+MyBatis+MySQL實(shí)現(xiàn)分頁功能的相關(guān)資料,文中介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-06-06如何搭建一個(gè)完整的Java開發(fā)環(huán)境
這篇文章主要教大家如何搭建一個(gè)完整的Java開發(fā)環(huán)境,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11使用ehcache三步搞定springboot緩存的方法示例
本次內(nèi)容主要介紹基于Ehcache 3.0來快速實(shí)現(xiàn)Spring Boot應(yīng)用程序的數(shù)據(jù)緩存功能。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-04-04基于Springboot執(zhí)行多個(gè)定時(shí)任務(wù)并動(dòng)態(tài)獲取定時(shí)任務(wù)信息
這篇文章主要為大家詳細(xì)介紹了基于Springboot執(zhí)行多個(gè)定時(shí)任務(wù)并動(dòng)態(tài)獲取定時(shí)任務(wù)信息,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04java時(shí)間戳與日期相互轉(zhuǎn)換工具詳解
這篇文章主要為大家詳細(xì)介紹了java各種時(shí)間戳與日期之間相互轉(zhuǎn)換的工具,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12數(shù)組與List之間相互轉(zhuǎn)換的方法詳解
本文是對數(shù)組與List之間相互轉(zhuǎn)換的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下。希望對大家有所幫助2013-10-10通過Java來測試JSON和Protocol Buffer的傳輸文件大小
這篇文章主要介紹了通過Java來測試JSON和Protocol Buffer的傳輸文件大小,Protocol Buffer(文中簡稱Protobuffer)是谷歌開發(fā)的新的文件傳輸格式,需要的朋友可以參考下2015-12-12java使用udp實(shí)現(xiàn)簡單多人聊天功能
這篇文章主要為大家詳細(xì)介紹了java使用udp實(shí)現(xiàn)簡單多人聊天功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02