ApplicationContextAware使用理解
問題背景
在我們的web程式中,用spring來管理各個例項(bean), 有時在程式中為了使用已被例項化的bean, 通常會用到這樣的程式碼:
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext-common.xml");
AbcService abcService = (AbcService)appContext.getBean("abcService");
但是這樣就會存在一個問題:因為它會重新裝載applicationContext-common.xml
並例項化上下文bean,如果有些執行緒配置類也是在這個配置檔案中,那麼會造成做相同工作的的執行緒會被啟兩次。一次是web容器初始化時啟動,另一次是上述程式碼顯示的例項化了一次。當於重新初始化一遍!!!!這樣就產生了冗餘。
解決方法
不用類似new ClassPathXmlApplicationContext()的方式,從已有的spring上下文取得已例項化的bean。通過ApplicationContextAware介面進行實現。
當一個類實現了這個介面(ApplicationContextAware)之後,這個類就可以方便獲得ApplicationContext中的所有bean。換句話說,就是這個類可以直接獲取spring配置檔案中,所有有引用到的bean物件。
ApplicationContextAware怎麼用
(1)方法類AppUtil實現ApplicationContextAware介面
@Component
public class AppUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
applicationContext = arg0;
}
public static Object getObject(String id) {
Object object = null;
object = applicationContext.getBean(id);
return object;
}
}
【備註】
(1)在spring的配置檔案中,註冊方法類AppUtil。之所以方法類AppUtil能夠靈活自如地獲取ApplicationContext,就是因為spring能夠為我們自動地執行了setApplicationContext。但是,spring不會無緣無故地為某個類執行它的方法的,所以,就很有必要通過註冊方法類AppUtil的方式告知spring有這樣子一個類的存在。這裡我們使用@Component
來進行註冊,或者我們也可以像下面這樣在配置檔案宣告bean:
<bean id="appUtil" class="com.htsoft.core.util.AppUtil"/>
(2)載入Spring配置檔案時,如果Spring配置檔案中所定義的Bean類實現了ApplicationContextAware 介面,那麼在載入Spring配置檔案時,會自動呼叫ApplicationContextAware 介面中的
public void setApplicationContext(ApplicationContext context) throws BeansException
方法,獲得ApplicationContext物件,ApplicationContext物件是由spring注入的。前提必須在Spring配置檔案中指定該類。
(3)使用靜態的成員ApplicationContext型別的物件。
使用場景備註
從ApplicationContextAware獲取ApplicationContext上下文的情況,僅僅適用於當前執行的程式碼和已啟動的Spring程式碼處於同一個Spring上下文,否則獲取到的ApplicationContext是空的。
比如我要為當前系統加入一個定時任務,定時重新整理Memcache快取。這個定時任務框架是公司的框架,下面是我的ApplicationContextAware 介面實現類:
@Component
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;//宣告一個靜態變數儲存
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("applicationContext正在初始化,application:"+appContext);
this.applicationContext=applicationContext;
}
public static <T> T getBean(Class<T> clazz){
if(applicationContext==null){
System.out.println("applicationContext是空的");
}else{
System.out.println("applicationContext不是空的");
}
return applicationContext.getBean(clazz);
}
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
}
定時任務類如下,定時任務初始化的時候,首先會呼叫作業類的public static Object getObject()
方法返回作業類的例項。
@Component
public class RemoteCacheJob extends AbstractSaturnJavaJob {
@Autowired
private AdsRemoteCacheJob adsRemoteCacheJob;
@Autowired
private ILogService logService;
// 例項化的過程:系統會首先呼叫作業類的public static Object getObject()方法,
// 如果返回為null,則呼叫作業類的無參構造方法來例項化;否則直接使用getObject()方法返回的物件作為作業類例項。
public static Object getObject() {
return ApplicationContextUtil.getBean(RemoteCacheJob .class);
}
@Override
public void handleJavaJob(String jobName, Integer shardItem, String shardParam, SaturnJobExecutionContext shardingContext)
throws InterruptedException {
System.out.println("處理定時任務");
}
}
啟動專案,Spring容器進行初始化,可以看到已經初始化了ApplicationContext :
然後執行定時任務外掛,首先去獲取ApplicationContext,但是此時的applicationContext是空的:
很顯然,定時任務是沒辦法獲取到專案所在Spring容器啟動之後的ApplicationContext。
相關文章
- ApplicationContextAware使用說明APPContext
- spring(1)-ApplicationContextAware詳解SpringAPPContext
- vuex使用理解Vue
- redis list 使用和理解Redis
- NSProxy的理解和使用
- promise的理解和使用Promise
- Node JS Buffer使用理解JS
- redis api的使用和理解RedisAPI
- React中理解並使用ReduxReactRedux
- 使用 go 理解 Lock-FreeGo
- Java泛型理解與使用Java泛型
- python 程式的使用和理解Python
- Spring Series---@Scheduled使用深度理解Spring
- 丐版stream流理解和使用
- AntDesign表單的理解與使用
- SpringBoot之ApplicationContextInitializer的理解和使用Spring BootAPPContext
- 白話理解和使用DOCKER VOLUMEDocker
- go中Tag的理解與使用Go
- 如何理解和使用膠囊網路
- ES6 Promise的使用和理解Promise
- git:rebase(變基)的使用和理解Git
- 理解並正確使用synchronized和volatilesynchronized
- 我是如何理解並使用maven的Maven
- 正確理解memcached,才能更好的使用
- 【git revert】使用以及理解(詳解)Git
- Flutter狀態管理之Provider的理解使用FlutterIDE
- 理解Python asyncio原理和簡潔使用方式Python
- 《Learning ELK Stack》6 使用Kibana理解資料
- Kotlin 字串教程:深入理解與使用技巧Kotlin字串
- 理解AI使用AI但成為不了AIAI
- Spring關於druid使用注入的深度理解SpringUI
- Android Handler機制理解和AsyncTask使用小記Android
- Kotlin直接使用控制元件ID原理解析Kotlin控制元件
- Web 效能優化:理解及使用 JavaScript 快取Web優化JavaScript快取
- 需求分析 - 你如何理解使用者痛點
- Java 8 Stream API: 深入理解與高效使用JavaAPI
- js與ios橋接使用WebViewJavascriptBridge簡單理解JSiOS橋接WebViewJavaScript
- Vue 開發之插槽(slot)的理解和使用Vue