https://blog.csdn.net/weixin_38361347/article/details/89304414
https://www.jianshu.com/p/9ea13b00b1d9
https://blog.csdn.net/zsw12013/article/details/51701671
____________________________________________________________________________________________________________________________
SpringBoot中獲取ApplicationContext的三種方式
ApplicationContext是什么?
簡單來說就是Spring中的容器,可以用來獲取容器中的各種bean組件,注冊監聽事件,加載資源文件等功能。
Application Context獲取的幾種方式
1 直接使用Autowired注入
@Component
public class Book1 {
@Autowired
private ApplicationContext applicationContext;
public void show (){
System.out.println(applicationContext.getClass());
}
}
2 利用 spring4.3 的新特性
使用spring4.3新特性但是存在一定的局限性,必須滿足以下兩點:
1 構造函數只能有一個,如果有多個,就必須有一個無參數的構造函數,此時,spring會調用無參的構造函數
2 構造函數的參數,必須在spring容器中存在
@Component
public class Book2 {
private ApplicationContext applicationContext;
public Book2(ApplicationContext applicationContext){
System.out.println(applicationContext.getClass());
this.applicationContext=applicationContext;
}
public void show (){
System.out.println(applicationContext.getClass());
}
}
3 實現spring提供的接口 ApplicationContextAware
spring 在bean 初始化后會判斷是不是ApplicationContextAware的子類,調用setApplicationContext()方法, 會將容器中ApplicationContext傳入進去
@Component
public class Book3 implements ApplicationContextAware {
private ApplicationContext applicationContext;
public void show (){
System.out.println(applicationContext.getClass());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
結果獲取三次:
class org.springframework.context.annotation.AnnotationConfigApplicationContext
class org.springframework.context.annotation.AnnotationConfigApplicationContext
class org.springframework.context.annotation.AnnotationConfigApplicationContext
---------------------
版權聲明:本文為CSDN博主「A 是小阿怪啊」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_38361347/article/details/89304414
___________________________________________________________________________________________________
在項目中我們經常會碰到這么一個場景,某些普通的JAVA類,這個類並沒有被Spring所管理,但是我們需要再這個類中調用到某些方法,是ioc容器中對象的方法,我們沒法再普通的JAVA類中通過spring的注解@Autowired和@Resource注入對象,在這種場景下,我么就可以使用方法獲取到ioc中的實例,並使用其方法。
在項目中獲取獲取beand方法多種多樣,這里大致列舉幾種
- 在初始化時保存ApplicationContext對象
- 通過Spring提供的utils類獲取ApplicationContext對象
- 繼承自抽象類ApplicationObjectSuppor
- 繼承自抽象類WebApplicationObjectSupport
- 實現接口ApplicationContextAware
- 通過Spring提供的ContextLoader
如果想了解每一種的用法可以參考此篇博文:https://blog.csdn.net/zsw12013/article/details/51701671
本片博文只具體展示一種配置,也是自身項目中遇到的獲取方式,就是第五中方式實現接口ApplicationContextAware,這種獲取方式適用於大多數項目內業務接口不方便注入的時候的調用
實現ApplicationContextAware接口的類必須要被spring所管理,要么在代碼中標記為ioc組件(類的路徑必須要被spring掃描到),要么在applicationContext.xml spring的配置文件配置為bean,不然會獲取不到上下文對象,調用這個類的普通JAVA類是沒有限制的。
工具類代碼
package com.wzh.config.utils; import org.apache.log4j.Logger; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; /** * <從Spring IOC容器中獲取Bean對象> <功能詳細描述> * @author wzh * @version 2018-09-23 19:32 * @see [相關類/方法] (可選) **/ @Component("beanHeader") public class BeanHeader implements ApplicationContextAware { private static Logger log = Logger.getLogger(BeanHeader.class); // 上下文對象 private static ApplicationContext applicationContext; /** * 實現ApplicationContextAware接口的回調方法,注入上下文對象 * @param applicationContext * @throws BeansException */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { BeanHeader.applicationContext = applicationContext; } /** * 獲取上下文對象 * @return applicationContext */ public static ApplicationContext getApplicationContext() { return applicationContext; } /** * 判斷上下文對象是否為空 * * @return */ public static boolean checkapplicationContext() { boolean flag = getApplicationContext() != null; if (!flag) { log.error("applicaitonContext未注入,實現ApplicationContextAware的類必須被spring管理"); } return flag; } /** * 根據name獲取bean * @param name * @param <T> * @return */ public static <T> T getBean(String name) { if (checkapplicationContext()) { return (T)getApplicationContext().getBean(name); } else { return null; } } /** * 根據class 獲取bean * @param clazz * @param <T> * @return */ public static <T> T getBean(Class<T> clazz) { if (checkapplicationContext()) { return getApplicationContext().getBean(clazz); } else { return null; } } /** * 根據name,以及Clazz返回指定的Bean * @param name * @param clazz * @param <T> * @return */ public static <T> T getBean(String name, Class<T> clazz) { if (checkapplicationContext()) { return getApplicationContext().getBean(name, clazz); } else { return null; } } }
下面我們來測試一下
首先是一個簡單的service 被spring管理
package com.wzh.demo.service.impl; import com.wzh.demo.service.SystemOutService; import org.springframework.stereotype.Service; /** * <簡單的輸出測試,沒有功能> * <功能詳細描述> * @author wzh * @version 2018-09-23 23:11 * @see [相關類/方法] (可選) **/ @Service("systemOutService") public class SystemOutServiceImp implements SystemOutService{ @Override public void sysout() { System.out.println("調用systemOutService 成功"); } }
junit 測試基類
package base; import com.wzh.application.Application; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; /** * junit 測試基類 */ //SpringJUnit支持,由此引入Spring-Test框架支持! @RunWith(SpringJUnit4ClassRunner.class) //啟動類,啟用隨即端口 @SpringBootTest(classes = Application.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) //web項目支持,webEnvironment屬性使用后不能用webAppconfiguration注解 //@WebAppConfiguration public class BaseJunit { @Test public void runJunitTest() { System.out.println("Junit 啟動測試"); } }
junit 測試類
import base.BaseJunit; import com.wzh.config.utils.BeanHeader; import com.wzh.demo.service.SystemOutService; import org.junit.Test; /** * <一句話功能描述> * <功能詳細描述> * @author wzh * @version 2018-09-23 23:18 * @see [相關類/方法] (可選) **/ public class BeanHeaderTest extends BaseJunit { @Test public void testBeanHeader() { SystemOutService service = BeanHeader.getBean("systemOutService"); service.sysout(); } }
運行方法,控制台輸出

_____________________________________________________________________________________________
獲取ApplicationContext進而獲取Ioc實例方法
在正常情況下 spring管理的類可直接調用Ioc容器中的實例,但在一些特殊情況下(例如攔截器中獲取dao實例),Bean需要實現某個功能,但該功能必須借助於Spring容器才能實現,此時就必須讓該Bean先獲取Spring容器,
spring提供了ApplicationContextAware接口,容器會自動檢索實現該接口的類進行spring上下文注入
import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import lombok.extern.slf4j.Slf4j; @Slf4j @Component public class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (SpringUtil.applicationContext == null) { SpringUtil.applicationContext = applicationContext; } log.info("ApplicationContext config success"); } // 獲取applicationContext public static ApplicationContext getApplicationContext() { return applicationContext; } // 通過name獲取 Bean. public static Object getBean(String name) { return getApplicationContext().getBean(name); } // 通過class獲取Bean. public static <T> T getBean(Class<T> clazz) { return getApplicationContext().getBean(clazz); } // 通過name,以及Clazz返回指定的Bean public static <T> T getBean(String name, Class<T> clazz) { return getApplicationContext().getBean(name, clazz); } }
使用例子,攔截器中獲取 redis緩存實例
public class AccessInterceptor implements HandlerInterceptor { private IStringCacheService cache = SpringUtil.getBean(IStringCacheService.class); ...... ...... ...... ...... ...... }