Spring通過ApplicationContext主動獲取bean的方法講解
問題1:
有個異步線程Runnable里面需要用到dao,無法通過AutoWired和compoment注解傳遞進來。
于是希望通過Spring context主動去獲取bean。
問題2:
getBean(name)獲取失敗。
解決:
默認的dao的name=類名(首字母小寫)
例如:
接口名稱:TemplateDao 則getName(“templateDao”)即可
通用的SpringContextUtil獲取Bean
1.實現(xiàn)ApplicationContextAware接口
/**
* spring上下文配置
* @author Mingchenchen
*
*/
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static Logger logger = Logger.getLogger(SpringContextUtil.class);
private static ApplicationContext applicationContext = null;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
logger.info("------SpringContextUtil setApplicationContext-------");
SpringContextUtil.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 注意 bean name默認 = 類名(首字母小寫)
* 例如: A8sClusterDao = getBean("k8sClusterDao")
* @param name
* @return
* @throws BeansException
*/
public static Object getBean(String name) throws BeansException {
return applicationContext.getBean(name);
}
/**
* 根據(jù)類名獲取到bean
* @param <T>
* @param clazz
* @return
* @throws BeansException
*/
@SuppressWarnings("unchecked")
public static <T> T getBeanByName(Class<T> clazz) throws BeansException {
try {
char[] cs=clazz.getSimpleName().toCharArray();
cs[0] += 32;//首字母大寫到小寫
return (T) applicationContext.getBean(String.valueOf(cs));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static boolean containsBean(String name) {
return applicationContext.containsBean(name);
}
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return applicationContext.isSingleton(name);
}
}
2.在web項目中的web.xml中配置加載Spring容器的Listener
<!-- 初始化Spring容器,讓Spring容器隨Web應用的啟動而自動啟動 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
getBeanByName(Class clazz)
這個方法更好使用,不過需要注意Dao和service的impl里面需要配置好名稱為@Service(“myService”)
規(guī)則為接口Service的類名首字母小寫。
第二種方式:
目前又做了個系統(tǒng)初始化的東東SystemInit,然后發(fā)現(xiàn)上面的getBean()用不了了??戳讼掳l(fā)現(xiàn)是因為在系統(tǒng)初始化的時候SpringContextUtil還沒有初始化,導致在SystemInit類里面的東西getBean()失敗。
于是小改造了下,把ApplicationContextAware放在SystemInit類,然后注入到SpringContextUtil,這樣就保證了在執(zhí)行系統(tǒng)初始化方法之前,applicationContext一定不是null。
/**
* spring上下文配置
* @author Mingchenchen
*
*/
public class SpringContextUtil {
private static Logger logger = Logger.getLogger(SpringContextUtil.class);
//@Autowired 沿用springTest的這種方法 是否會更好?
//ApplicationContext ctx;
private static ApplicationContext applicationContext = null;
public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
logger.info("------SpringContextUtil setApplicationContext-------");
SpringContextUtil.applicationContext = applicationContext;
}
//注意此處變成了static
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 注意 bean name默認 = 類名(首字母小寫)
* 例如: A8sClusterDao = getBean("k8sClusterDao")
* @param name
* @return
* @throws BeansException
*/
public static Object getBean(String name) throws BeansException {
return applicationContext.getBean(name);
}
/**
* 根據(jù)類名獲取到bean
* @param <T>
* @param clazz
* @return
* @throws BeansException
*/
@SuppressWarnings("unchecked")
public static <T> T getBeanByName(Class<T> clazz) throws BeansException {
try {
char[] cs=clazz.getSimpleName().toCharArray();
cs[0] += 32;//首字母大寫到小寫
return (T) applicationContext.getBean(String.valueOf(cs));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static boolean containsBean(String name) {
return applicationContext.containsBean(name);
}
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return applicationContext.isSingleton(name);
}
}
/**
* Descripties: 系統(tǒng)初始化
* @author wangkaiping
* 2016年5月23日 上午11:58:09
*/
@Component
public class SystemInit implements InitializingBean,ApplicationContextAware{
private static Logger logger = Logger.getLogger(SystemInit.class);
@Autowired
private ClusterDao clusterDao;
@Override
public void afterPropertiesSet() throws Exception {
logger.info("--------------系統(tǒng)初始化中-------------------");
initClusterCache();//初始化集群數(shù)據(jù) 必須最開始完成
initRefreshAppStatusTask();
initUpdateAppStatusToDB();
initUpdateSession();
logger.info("--------------系統(tǒng)初始化完成-------------------");
}
/**
* 1.初始化集群數(shù)據(jù)
*/
private void initClusterCache(){
logger.info("1.初始化集群信息到緩存中:ClusterCache開始");
//查詢數(shù)據(jù)庫所有的集群數(shù)據(jù)
List<ClusterEntity> allClusterInfoList = clusterDao.selectAll(ClusterEntity.class, "delete_flag=0");
for (ClusterEntity k8sClusterEntity : allClusterInfoList) {
ClusterCache.put(k8sClusterEntity.getUuid() , k8sClusterEntity);//存入緩存
}
logger.info("1.初始化集群信息到緩存中:ClusterCache完成,總共" + allClusterInfoList.size() + "條數(shù)據(jù)");
}
/**
* 2.初始化異步任務:刷新所有應用狀態(tài)
*/
private void initRefreshAppStatusTask() {
logger.info("2.初始化任務:RefreshAllAppStatusTask 刷新應用下的k8s的pod狀態(tài)并存入待更新隊列");
RefreshAppStatusExcutor.init();
logger.info("2.初始化任務:RefreshAllAppStatusTask 完成");
}
/**
* 3.初始化異步任務:更新狀態(tài)到數(shù)據(jù)庫
*/
private void initUpdateAppStatusToDB() {
logger.info("3.初始化任務:RefreshToDBTask 從待更新Appinstance隊列取出數(shù)據(jù)并更新數(shù)據(jù)庫");
UpdateAppStatusToDBExcutor.init();
logger.info("3.初始化任務:RefreshToDBTask 完成");
}
/**
* 4. 初始化異步任務: 更新用戶的所有session
*/
private void initUpdateSession() {
logger.info("4.初始化任務:更新session開始");
UserSessionUpdateExcutor.init();
logger.info("4.初始化任務:更新session結(jié)束");
}
////////////////////////////////////////////////////////////////
//此方法一定不要寫成static
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
//實際上是把applicationContext傳入到了SpringContextUtil里面
SpringContextUtil.setApplicationContext(applicationContext);
}
}
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
相關(guān)文章
springboot接入netty實現(xiàn)在線統(tǒng)計人數(shù)
本文主要介紹了springboot接入netty實現(xiàn)在線統(tǒng)計人數(shù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-03-03
Java使用備忘錄模式實現(xiàn)過關(guān)類游戲功能詳解
這篇文章主要介紹了Java使用備忘錄模式實現(xiàn)過關(guān)類游戲功能,結(jié)合實例形式詳細分析了java備忘錄模式的概念、原理及其在過關(guān)類游戲中的具體應用方法,需要的朋友可以參考下2018-04-04
MyBatisPlus利用Service實現(xiàn)獲取數(shù)據(jù)列表
這篇文章主要為大家詳細介紹了怎樣使用 IServer 提供的 list 方法查詢多條數(shù)據(jù),這些方法將根據(jù)查詢條件獲取多條數(shù)據(jù),感興趣的可以了解一下2022-06-06
mybatisplus邏輯刪除基本實現(xiàn)和坑點解決
這篇文章主要介紹了mybatisplus邏輯刪除基本實現(xiàn)和坑點解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
spring的事務傳播屬性REQUIRED_NESTED原理
這篇文章主要介紹了spring的事務傳播屬性REQUIRED_NESTED原理,在spring中,要想使用事務中的回滾點,可以使用傳播屬性NESTED,需要的朋友可以參考下2023-05-05

