Springboot如何獲取上下文ApplicationContext
Springboot獲取上下文ApplicationContext
在項(xiàng)目中遇到了一個(gè)場(chǎng)景,就是通過(guò)獲得上下文然后獲取特定的bean。在此遇到了不小的坑,故留下這個(gè)篇文章,做個(gè)記錄。
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContextUtil implements ApplicationContextAware {
/**
* 上下文對(duì)象實(shí)例
*/
private static ApplicationContext applicationContext;
@Autowired
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 獲取applicationContext
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 通過(guò)name獲取 Bean.
* @param name
* @return
*/
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
/**
* 通過(guò)class獲取Bean.
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
/**
* 通過(guò)name,以及Clazz返回指定的Bean
* @param name
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
}
看上面的代碼,可以看到在工具類中一開(kāi)始是聲明了一個(gè)ApplicationContext類型的靜態(tài)變量,但是由于靜態(tài)變量是不能被Spring容器管理的,一開(kāi)始用正常的getter和setter方法不能獲取到特定的bean,實(shí)踐證明,需要在此變量的setter方法上加上@Autowired注解,并且去除setter方法中的static關(guān)鍵字。才可實(shí)現(xiàn)特定bean的注入。
springboot的應(yīng)用上下文
springboot上下文有兩個(gè)
ServletWebServerApplicationContextAnnotationConfigServletWebServerApplicationContext(繼承上面)
ServletWebServerApplicationContext
該類屬于spring-boot-2.1.1Release.jar中,是自springboot誕生就衍生出來(lái)的,是spring框架的應(yīng)用上下文Application的子類。
多說(shuō)無(wú)益,show me code
擴(kuò)展的功能
首先讓我們來(lái)看一下,這個(gè)類到底做了什么,有什么存在的價(jià)值?
private volatile WebServer webServer;
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
在此類中有個(gè)WebServer成員變量,讓我們用腳趾頭想一下也應(yīng)該可以知道,這其實(shí)就是web服務(wù)對(duì)象,也基本上可以猜測(cè)就是跟tomcat相關(guān)了(當(dāng)然也可以是其他web服務(wù)器,如jetty)
然后我們又發(fā)現(xiàn)了onRefresh方法,相信我們并不陌生,這就是spring核心refresh方法的中一個(gè)鉤子方法(即表明此時(shí)已經(jīng)加載所有配置bean),進(jìn)行WebServer對(duì)象的創(chuàng)建
@Override
protected void finishRefresh() {
super.finishRefresh();
WebServer webServer = startWebServer();
if (webServer != null) {
publishEvent(new ServletWebServerInitializedEvent(webServer, this));
}
}
我們又發(fā)現(xiàn)該類存在finishRefresh,仔細(xì)想一下,這個(gè)也是spring核心#refresh方法中的一個(gè)鉤子方法(不過(guò)這個(gè)特別,因?yàn)樵摲椒ㄊ莚efresh方法中的最后一步,即會(huì)去實(shí)例化spring容器中的所有beandefinition對(duì)象)
首先贊一個(gè),這個(gè)很巧妙,調(diào)用了super.finishRefresh() ,并沒(méi)有丟棄父類的邏輯功能(這點(diǎn)在多態(tài)中,我相信還是會(huì)有人犯錯(cuò),本來(lái)是擴(kuò)展功能,但是直接重寫(xiě),丟棄了父類的方法,當(dāng)然spring框架開(kāi)發(fā)大佬肯定不會(huì)犯這種錯(cuò)誤,對(duì)吧?。?/p>
第二點(diǎn)重點(diǎn)來(lái)了,就是startWebServer,也就是在spring完成實(shí)例化之后,就會(huì)去啟動(dòng)web服務(wù)。
AnnotationConfigServletWebServerApplicationContext
小結(jié)一下:
首先此類是springboot啟動(dòng)運(yùn)行run()創(chuàng)建ApplicationContext的實(shí)現(xiàn)類,不過(guò)很可惜,該類并沒(méi)有很強(qiáng)的實(shí)質(zhì)性擴(kuò)展。
**唯一作用就是擁有了通過(guò)注解加載配置類的作用,即和AnnotationConfigApplication一樣,只不過(guò)springboot的運(yùn)行啟動(dòng)已經(jīng)是通過(guò)注解加載bean類**
(雖然是雞肋,不過(guò)這也符合spring創(chuàng)建類的一貫風(fēng)格,就是每個(gè)類都是高內(nèi)聚的,即每個(gè)類除了父類的功能之外,還都擁有其他擴(kuò)展的作用。即使創(chuàng)建出來(lái)還沒(méi)有用到就被遺棄,但仍然不能阻止spring開(kāi)發(fā)大佬創(chuàng)建該類,哈哈)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決springboot遇到autowire注入為null的問(wèn)題
這篇文章主要介紹了解決springboot遇到autowire注入為null的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03
java從命令行獲取數(shù)據(jù)的三種方式代碼實(shí)例
這篇文章主要介紹了java從命令行獲取數(shù)據(jù)的三種方式代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
java中replaceAll替換圓括號(hào)實(shí)例代碼
正則表達(dá)式的保留字符主要有:圓括號(hào)、方括號(hào)、花括號(hào)、豎線、橫線、點(diǎn)號(hào)、加號(hào)、星號(hào)、反斜桿等等,下面這篇文章主要給大家介紹了關(guān)于java中replaceAll替換圓括號(hào)的相關(guān)資料,需要的朋友可以參考下2022-10-10
Minio環(huán)境部署過(guò)程及如何配置HTTPS域名
MinIO?是一個(gè)對(duì)象存儲(chǔ)系統(tǒng),數(shù)據(jù)需要存儲(chǔ)在宿主機(jī)上,容器的重啟不影響數(shù)據(jù),因此我們需要為?MinIO?創(chuàng)建一個(gè)掛載目錄,用于持久化存儲(chǔ)數(shù)據(jù),本文詳細(xì)介紹了如何部署MinIO,并通過(guò)配置反向代理和HTTPS來(lái)提升其安全性,感興趣的朋友一起看看吧2025-03-03
mybatis自動(dòng)填充時(shí)間字段示例代碼
這篇文章主要給大家介紹了關(guān)于mybatis自動(dòng)填充時(shí)間字段的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01
java實(shí)現(xiàn)二分法查找出數(shù)組重復(fù)數(shù)字
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)二分法查找出數(shù)組重復(fù)數(shù)字,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11

