获取Spring ApplicationContext容器上下文对象实例
Spring ApplicationContext 容器可以加載配置文件中定義的 bean,將所有的 bean 集中在一起,當(dāng)有請(qǐng)求的時(shí)候分配 bean。如果說(shuō)BeanFactory是Spring的心臟,那么ApplicationContext就是完整的身軀了。ApplicationContext由BeanFactory派生而來(lái),提供了更多面向?qū)嶋H應(yīng)用的功能。另外,它增加了企業(yè)所需要的功能,比如,從屬性文件中解析文本信息和將事件傳遞給所指定的監(jiān)聽器。這個(gè)容器在 org.springframework.context.ApplicationContext interface 接口中定義。
ApplicationContext的初始化和BeanFactory有一個(gè)重大的區(qū)別:BeanFactory在初始化容器時(shí),并未實(shí)例化Bean,直到第一次訪問某個(gè)Bean時(shí)才實(shí)例目標(biāo)Bean;而ApplicationContext則在初始化應(yīng)用上下文時(shí)就實(shí)例化所有單實(shí)例的Bean。因此ApplicationContext的初始化時(shí)間會(huì)比BeanFactory稍長(zhǎng)一些,不過稍后的調(diào)用則沒有這樣的缺陷了。
傳統(tǒng)的獲取ApplicationContext的方式有很多種,下面小編簡(jiǎn)單地介紹幾種常用的方式!在獲取ApplicationContext實(shí)例后,就可以調(diào)用getBean(beanName)返回Bean了。
為了驗(yàn)證,假設(shè)已經(jīng)構(gòu)建了Spring Boot項(xiàng)目,在包c(diǎn)om.eg.wiener.config中新增測(cè)試類。
package com.eg.wiener.config; import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service; @Service
public class BeanTest { @Bean
public BeanTest getBeanObj() {
BeanTest bean = new BeanTest();
System.out.println("調(diào)用方法:" + bean);
return bean;
} }
直接注入
@Autowired
private ApplicationContext ctx; @GetMapping("/getContext")
public String getContext(){
Object bean1 = ctx.getBean("getBeanObj");
return String.format(" ctx 打印bean %s", bean1);
}
啟動(dòng)項(xiàng)目,可以找到日志:
2020-06-27 10:50:16.879 INFO 12272 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2187 ms
調(diào)用方法:com.eg.wiener.config.BeanTest@3c74aa0d
說(shuō)明bean已經(jīng)被注入Spring容器,默認(rèn)bean的名稱就是其方法名。在瀏覽器訪問函數(shù)getContext() 時(shí),會(huì)返回bean【getBeanObj】的信息:
ctx 打印bean com.eg.wiener.config.BeanTest@3c74aa0d
和啟動(dòng)時(shí)日志打印的bean 信息一致,而且,沒有執(zhí)行方法getBeanObj()。
實(shí)現(xiàn)ApplicationContextAware接口
創(chuàng)建一個(gè)實(shí)體類并實(shí)現(xiàn)ApplicationContextAware接口,重寫接口內(nèi)的setApplicationContext方法來(lái)完成獲取ApplicationContext實(shí)例的方法,代碼如下所示:
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component; @Component
public class ApplicationContextProvider implements ApplicationContextAware {
/**
* 上下文對(duì)象實(shí)例
*/
private ApplicationContext applicationContext; @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
} /**
* 獲取applicationContext
*
* @return
*/
public ApplicationContext getApplicationContext() {
return applicationContext;
} /**
* 通過name獲取 Bean.
*
* @param name
* @return
*/
public Object getBean(String name) {
return getApplicationContext().getBean(name);
} /**
* 通過class獲取Bean.
*
* @param clazz
* @param <T>
* @return
*/
public <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
} /**
* 通過name,以及Clazz返回指定的Bean
*
* @param name
* @param clazz
* @param <T>
* @return
*/
public <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
在拿到ApplicationContext對(duì)象實(shí)例后就可以獲取Bean的注入實(shí)例對(duì)象,在ApplicationContextProvider類內(nèi)簡(jiǎn)單的實(shí)現(xiàn)了幾個(gè)方法來(lái)獲取指定的Bean實(shí)例,也可以添加更多的方法來(lái)完成更多的業(yè)務(wù)邏輯。
這里要注意ApplicationContextProvider類上的@Component注解是不可以去掉的,去掉后Spring就不會(huì)自動(dòng)調(diào)用setApplicationContext方法來(lái)為我們?cè)O(shè)置上下文實(shí)例。我簡(jiǎn)單的創(chuàng)建了一個(gè)API,以便測(cè)試,效果可以達(dá)到要求,代碼如下:
@Autowired
private ApplicationContextProvider provider; @GetMapping("/getContextProd")
public String getContextProd(){
Object bean = provider.getBean("getBeanObj");
return String.format(" ApplicationContextProvider 打印bean %s", bean);
}
在自定義AutoConfiguration中獲取
有時(shí)候我們需要實(shí)現(xiàn)自定義的Spring starter,并在自定義的AutoConfiguration中使用ApplicationContext,Spring在初始化AutoConfiguration時(shí)會(huì)自動(dòng)傳入ApplicationContext,這時(shí)我們就可以使用下面的方式來(lái)獲取ApplicationContext:
@Configuration
@EnableFeignClients("com.yidian.data.interfaces.client")
public class FeignAutoConfiguration { FeignAutoConfiguration(ApplicationContext context) {
// 在初始化AutoConfiguration時(shí)會(huì)自動(dòng)傳入ApplicationContext
doSomething(context);
}}
啟動(dòng)時(shí)獲取ApplicationContext
在啟動(dòng)Spring Boot項(xiàng)目時(shí),需要調(diào)用SpringApplication.run()方法,而run()方法的返回值就是ApplicationContext,我們可以把run()方法返回的ApplicationContext對(duì)象保存下來(lái),方便隨時(shí)使用。下面使用這個(gè)返回示例獲取Bean示例:
private static ApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext = SpringApplication.run(WienerApplication.class, args);
Object bean1 = applicationContext.getBean("getBeanObj");
System.out.println(String.format("打印bean1 %s", bean1));
bean1 = applicationContext.getBean("getBeanObj");
System.out.println(String.format("打印bean2 %s", bean1));
}
項(xiàng)目啟動(dòng)后,在日志中可以發(fā)現(xiàn)如下三條記錄:
調(diào)用方法:com.eg.wiener.config.BeanTest@3c74aa0d
打印bean1 com.eg.wiener.config.BeanTest@3c74aa0d
打印bean2 com.eg.wiener.config.BeanTest@3c74aa0d
通過WebApplicationContextUtils獲取
Spring提供了一個(gè)工具類WebApplicationContextUtils用于獲取ApplicationContext對(duì)象,它是Spring框架基礎(chǔ)包中的類,該方法必須依賴Servlet容器。
WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc);
WebApplicationContextUtils.getWebApplicationContext(ServletContext sc);
測(cè)試用例:
關(guān)于以上5種獲取ApplicationContext上下文對(duì)象實(shí)例的方式,大家有什么看法,歡迎留言討論,也希望大家多多點(diǎn)贊,祝各位生活愉快。
Reference
https://www.jianshu.com/p/ef7739a01cb0
總結(jié)
以上是生活随笔為你收集整理的获取Spring ApplicationContext容器上下文对象实例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 「Log」2023.8.23 小记
- 下一篇: 做思维导图?chatmoney轻轻松松拿