ApplicationContextAware實現AppContextHolder(含github原始碼)
專案地址https://github.com/flylib/sword/tree/master/sword-springboot
父專案是https://github.com/flylib/sword
應用場景:
一般情況下,使用SpringMVC/SpringBoot的時候,各種bean註冊到Spring容器裡了,然後在需要這個bean的地方,
使用@Autowired
或者@Resource
標註的bean都可以被自動注入。 但是在某些場景下,
需要手動注入。比如在一個Util裡面,這個Util裡面的方法都是static的,這個時候,如果需要獲取Spring容器中的某個
bean,或者獲取到ApplicationContext, 這個時候,就需要一個ApplicationContext Holder的東西,這裡命名為AppContextHolder
其實Spring裡有一個介面就是為了這個應用場景而生的ApplicationContextAware
本人就開發了一個com.appjishu.swordboot.boot.AppContextHolder
實現了這個介面, 原始碼如下:
package com.appjishu.swordboot.boot;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context. ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
*
* @author liushaoming
*
*/
@Component
public class AppContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext (ApplicationContext applicationContext) throws BeansException {
if (AppContextHolder.applicationContext == null) {
AppContextHolder.applicationContext = applicationContext;
}
}
// 獲取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);
}
}
使用的時候,很簡單, 就像使用Spring原生的ApplicationContext一樣, 現在要獲取一個已經註冊到容器裡的一個bean Student
@Configuration
public class SysConfig {
@Bean(name = "myStudent")
public Student student() {
Student student=new Student();
student.setName("Frank Liu");
student.setAddress("Shanghai");
return student;
}
}
使用AppContextHolder獲取bean的操作
Student student0 = (Student) AppContextHolder.getBean("myStudent");
// 或者
Student student1 = (Student) AppContextHolder.getBean(Student.class);
log.info("student0.name={}", student0.getName());
測試方法:
在idea/eclipse裡,匯入maven專案sword-springboot, 右鍵執行SwordBootApp -> run as -> Java Application
這是一個springboot專案,開啟瀏覽器訪問地址http://localhost:15000/test
可以執行測試AppContextHolder的測試程式碼, 貼出TestUtil裡的方法
public class TestUtil {
private static final Logger log = LoggerFactory.getLogger(TestUtil.class);
public static void testAppContextHolder() {
log.info("--testAppContextHolder start---");
Student student0 = (Student) AppContextHolder.getBean("myStudent");
Student student1 = (Student) AppContextHolder.getBean(Student.class);
// 如果"student0 == student1"成立,則驗證了AppContextHolder的確能獲取到Spring容器ApplicationContext
// 而且Spring容器預設註冊bean使用的是單例模式
log.info("student0==student1? {}", student0 == student1);
log.info("-------------------");
log.info("student0.name={}", student0.getName());
log.info("student0.address={}", student0.getAddress());
log.info("-------------------");
log.info("student1.name={}", student1.getName());
log.info("student1.address={}", student1.getAddress());
log.info("--testAppContextHolder done---");
}
}
列印結果: 說明測試成功了
2019-01-06 15:43:47.563 INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil : --testAppContextHolder start---
2019-01-06 15:43:47.564 INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil : student0==student1? true
2019-01-06 15:43:47.564 INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil : -------------------
2019-01-06 15:43:47.565 INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil : student0.name=Frank Liu
2019-01-06 15:43:47.565 INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil : student0.address=Shanghai
2019-01-06 15:43:47.566 INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil : -------------------
2019-01-06 15:43:47.566 INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil : student1.name=Frank Liu
2019-01-06 15:43:47.566 INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil : student1.address=Shanghai
2019-01-06 15:43:47.566 INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil : --testAppContextHolder done---
注意事項:
AppContextHolder在SpringBoot裡使用,只需要在類名AppContextHolder
前標註@Component
如果在SpringMVC裡使用的,需要用@Component標註類AppContextHolder, 並且在applicationContext.xml裡面設定
包含AppContextHolder所在的package, 或者直接用bean
標籤來註冊它。
專案地址https://github.com/flylib/sword/tree/master/sword-springboot
父專案是https://github.com/flylib/sword