Spring通過ApplicationContext主動(dòng)獲取bean的方法講解
問題1:
有個(gè)異步線程Runnable里面需要用到dao,無法通過AutoWired和compoment注解傳遞進(jìn)來。
于是希望通過Spring context主動(dòng)去獲取bean。
問題2:
getBean(name)獲取失敗。
解決:
默認(rèn)的dao的name=類名(首字母小寫)
例如:
接口名稱:TemplateDao 則getName(“templateDao”)即可
通用的SpringContextUtil獲取Bean
1.實(shí)現(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默認(rèn) = 類名(首字母小寫)
* 例如: 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項(xiàng)目中的web.xml中配置加載Spring容器的Listener
<!-- 初始化Spring容器,讓Spring容器隨Web應(yīng)用的啟動(dòng)而自動(dòng)啟動(dòng) -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
getBeanByName(Class clazz)
這個(gè)方法更好使用,不過需要注意Dao和service的impl里面需要配置好名稱為@Service(“myService”)
規(guī)則為接口Service的類名首字母小寫。
第二種方式:
目前又做了個(gè)系統(tǒng)初始化的東東SystemInit,然后發(fā)現(xiàn)上面的getBean()用不了了??戳讼掳l(fā)現(xiàn)是因?yàn)樵谙到y(tǒng)初始化的時(shí)候SpringContextUtil還沒有初始化,導(dǎo)致在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的這種方法 是否會(huì)更好?
//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默認(rèn) = 類名(首字母小寫)
* 例如: 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.初始化異步任務(wù):刷新所有應(yīng)用狀態(tài)
*/
private void initRefreshAppStatusTask() {
logger.info("2.初始化任務(wù):RefreshAllAppStatusTask 刷新應(yīng)用下的k8s的pod狀態(tài)并存入待更新隊(duì)列");
RefreshAppStatusExcutor.init();
logger.info("2.初始化任務(wù):RefreshAllAppStatusTask 完成");
}
/**
* 3.初始化異步任務(wù):更新狀態(tài)到數(shù)據(jù)庫
*/
private void initUpdateAppStatusToDB() {
logger.info("3.初始化任務(wù):RefreshToDBTask 從待更新Appinstance隊(duì)列取出數(shù)據(jù)并更新數(shù)據(jù)庫");
UpdateAppStatusToDBExcutor.init();
logger.info("3.初始化任務(wù):RefreshToDBTask 完成");
}
/**
* 4. 初始化異步任務(wù): 更新用戶的所有session
*/
private void initUpdateSession() {
logger.info("4.初始化任務(wù):更新session開始");
UserSessionUpdateExcutor.init();
logger.info("4.初始化任務(wù):更新session結(jié)束");
}
////////////////////////////////////////////////////////////////
//此方法一定不要寫成static
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
//實(shí)際上是把a(bǔ)pplicationContext傳入到了SpringContextUtil里面
SpringContextUtil.setApplicationContext(applicationContext);
}
}
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章
springboot接入netty實(shí)現(xiàn)在線統(tǒng)計(jì)人數(shù)
本文主要介紹了springboot接入netty實(shí)現(xiàn)在線統(tǒng)計(jì)人數(shù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-03-03
Java使用備忘錄模式實(shí)現(xiàn)過關(guān)類游戲功能詳解
這篇文章主要介紹了Java使用備忘錄模式實(shí)現(xiàn)過關(guān)類游戲功能,結(jié)合實(shí)例形式詳細(xì)分析了java備忘錄模式的概念、原理及其在過關(guān)類游戲中的具體應(yīng)用方法,需要的朋友可以參考下2018-04-04
MyBatisPlus利用Service實(shí)現(xiàn)獲取數(shù)據(jù)列表
這篇文章主要為大家詳細(xì)介紹了怎樣使用 IServer 提供的 list 方法查詢多條數(shù)據(jù),這些方法將根據(jù)查詢條件獲取多條數(shù)據(jù),感興趣的可以了解一下2022-06-06
mybatisplus邏輯刪除基本實(shí)現(xiàn)和坑點(diǎn)解決
這篇文章主要介紹了mybatisplus邏輯刪除基本實(shí)現(xiàn)和坑點(diǎn)解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
SpringBoot實(shí)現(xiàn)驗(yàn)證碼的案例分享
驗(yàn)證碼可以有效防止其他人對(duì)某一個(gè)特定的注冊(cè)用戶用特定的程序,破解方式進(jìn)行不斷的登錄嘗試,我們其實(shí)很經(jīng)??吹?登錄一些網(wǎng)站其實(shí)是需要驗(yàn)證碼的,所以本文給大家分享了SpringBoot實(shí)現(xiàn)驗(yàn)證碼的案例,需要的朋友可以參考下2024-11-11
spring的事務(wù)傳播屬性REQUIRED_NESTED原理
這篇文章主要介紹了spring的事務(wù)傳播屬性REQUIRED_NESTED原理,在spring中,要想使用事務(wù)中的回滾點(diǎn),可以使用傳播屬性NESTED,需要的朋友可以參考下2023-05-05

