獲取Spring ApplicationContext容器上下文對象實例


      Spring ApplicationContext 容器可以加載配置文件中定義的 bean,將所有的 bean 集中在一起,當有請求的時候分配 bean。如果說BeanFactory是Spring的心臟,那么ApplicationContext就是完整的身軀了。ApplicationContext由BeanFactory派生而來,提供了更多面向實際應用的功能。另外,它增加了企業所需要的功能,比如,從屬性文件中解析文本信息和將事件傳遞給所指定的監聽器。這個容器在 org.springframework.context.ApplicationContext interface 接口中定義。

      ApplicationContext的初始化和BeanFactory有一個重大的區別:BeanFactory在初始化容器時,並未實例化Bean,直到第一次訪問某個Bean時才實例目標Bean;而ApplicationContext則在初始化應用上下文時就實例化所有單實例的Bean。因此ApplicationContext的初始化時間會比BeanFactory稍長一些,不過稍后的調用則沒有這樣的缺陷了。

傳統的獲取ApplicationContext的方式有很多種,下面小編簡單地介紹幾種常用的方式!在獲取ApplicationContext實例后,就可以調用getBean(beanName)返回Bean了。

       為了驗證,假設已經構建了Spring Boot項目,在包com.eg.wiener.config中新增測試類。

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("調用方法:" + bean); return bean; } }

直接注入

 @Autowired  private ApplicationContext ctx; @GetMapping("/getContext") public String getContext(){ Object bean1 = ctx.getBean("getBeanObj"); return String.format(" ctx 打印bean %s", bean1); }

      啟動項目,可以找到日志:

2020-06-27 10:50:16.879  INFO 12272 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2187 ms 調用方法:com.eg.wiener.config.BeanTest@3c74aa0d

      說明bean已經被注入Spring容器,默認bean的名稱就是其方法名。在瀏覽器訪問函數getContext() 時,會返回bean【getBeanObj】的信息:

ctx 打印bean com.eg.wiener.config.BeanTest@3c74aa0d

      和啟動時日志打印的bean 信息一致,而且,沒有執行方法getBeanObj()。

實現ApplicationContextAware接口

       創建一個實體類並實現ApplicationContextAware接口,重寫接口內的setApplicationContext方法來完成獲取ApplicationContext實例的方法,代碼如下所示:

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 { /** * 上下文對象實例 */
    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對象實例后就可以獲取Bean的注入實例對象,在ApplicationContextProvider類內簡單的實現了幾個方法來獲取指定的Bean實例,也可以添加更多的方法來完成更多的業務邏輯。

      這里要注意ApplicationContextProvider類上的@Component注解是不可以去掉的,去掉后Spring就不會自動調用setApplicationContext方法來為我們設置上下文實例。我簡單的創建了一個API,以便測試,效果可以達到要求,代碼如下:

 @Autowired private ApplicationContextProvider provider; @GetMapping("/getContextProd") public String getContextProd(){ Object bean = provider.getBean("getBeanObj"); return String.format(" ApplicationContextProvider 打印bean %s", bean); }

 在自定義AutoConfiguration中獲取

      有時候我們需要實現自定義的Spring starter,並在自定義的AutoConfiguration中使用ApplicationContext,Spring在初始化AutoConfiguration時會自動傳入ApplicationContext,這時我們就可以使用下面的方式來獲取ApplicationContext:

@Configuration @EnableFeignClients("com.yidian.data.interfaces.client") public class FeignAutoConfiguration { FeignAutoConfiguration(ApplicationContext context) { // 在初始化AutoConfiguration時會自動傳入ApplicationContext
doSomething(context); }}

 

啟動時獲取ApplicationContext

      在啟動Spring Boot項目時,需要調用SpringApplication.run()方法,而run()方法的返回值就是ApplicationContext,我們可以把run()方法返回的ApplicationContext對象保存下來,方便隨時使用。下面使用這個返回示例獲取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)); }

      項目啟動后,在日志中可以發現如下三條記錄:

調用方法:com.eg.wiener.config.BeanTest@3c74aa0d
打印bean1 com.eg.wiener.config.BeanTest@3c74aa0d
打印bean2 com.eg.wiener.config.BeanTest@3c74aa0d

通過WebApplicationContextUtils獲取

      Spring提供了一個工具類WebApplicationContextUtils用於獲取ApplicationContext對象,它是Spring框架基礎包中的類,該方法必須依賴Servlet容器。

WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc);
WebApplicationContextUtils.getWebApplicationContext(ServletContext sc);

     測試用例: 

@GetMapping("/getMyBean")
public String getMyBean(HttpServletRequest request)throws Exception{
  ServletContext sc = request.getSession().getServletContext();
  ApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
  BeanTest bean = ac.getBean("getBeanObj");
  return String.format(" 當前bean是 %s", bean);
}

      關於以上5種獲取ApplicationContext上下文對象實例的方式,大家有什么看法,歡迎留言討論,也希望大家多多點贊,祝各位生活愉快。 

Reference

    https://www.jianshu.com/p/ef7739a01cb0

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM