SpringBoot靜態(tài)方法調(diào)用Spring容器bean的三種解決方案
問題分析
今天一個(gè)小伙伴和我說@Autowired 注入的Bean為null值,經(jīng)過一番溝通后,我發(fā)現(xiàn)原來他需要在靜態(tài)方法中調(diào)用容器Bean,大致將代碼貼出來給大家看看:
//模擬錯(cuò)誤的使用方式 @Autowired private static RedisUtil redisUtilBean; public static String getMsgByRedis(){ redisUtilBean.get("xxx") //這里redisUtilBean一定會(huì)是NULL值 }
為什么會(huì)出現(xiàn)這種情況?原因是Spring容器的依賴注入是依賴set方法,而set方法是實(shí)例對(duì)象的方法,注入依賴時(shí)是無法注入靜態(tài)成員變量的,在調(diào)用的時(shí)候依賴的Bean才會(huì)為null;
解決方案一
使用@PostConstruct注解,
@Autowired private RedisUtil redisUtilBean; //由于靜態(tài)方法無法使用注入的Bean 定義靜態(tài)變量 private static RedisUtil redisUtil; //當(dāng)容器實(shí)例化當(dāng)前受管Bean時(shí)@PostConstruct注解的方法會(huì)被自動(dòng)觸發(fā),借此來實(shí)現(xiàn)靜態(tài)變量初始化 @PostConstruct public void init(){ this.redisUtil = redisUtilBean; } public static String getMsgByRedis(){ redisUtil.get("xxx") //這里可以正常使用 }
解決方案二
利用springboot的啟動(dòng)類中,SpringApplication.run() 方法返回的是一個(gè)ConfigurableApplicationContext對(duì)象通過定義static變量ConfigurableApplicationContext,利用容器的getBean方法獲得依賴對(duì)象;
@SpringBootApplication @EnableTransactionManagement public class Application { //定義靜態(tài)的ApplicationContext public static ConfigurableApplicationContext applicationContext; public static void main(String[] args) { applicationContext = SpringApplication.run(Application.class, args); } } //調(diào)用 注意Application是我們SpringBoot的啟動(dòng)類 public static String getMsgByRedis(){ Application.applicationContext..getBean(RedisUtil .class).get("xxx") }
解決方案三
在我們以前SpringMVC中常用的工具類,通過實(shí)現(xiàn)ApplicationContextAware接口,網(wǎng)上也很多這里就把工具類貼出來即可;
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.toher.common.utils.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.Map; /** * 以靜態(tài)變量保存Spring ApplicationContext, 可在任何代碼任何地方任何時(shí)候中取出ApplicaitonContext. * * @author 李懷明 * @version 2017-01-02 */ @Component public class SpringContextHolder implements ApplicationContextAware { private static ApplicationContext applicationContext; //實(shí)現(xiàn)ApplicationContextAware接口的context注入函數(shù), 將其存入靜態(tài)變量. public void setApplicationContext(ApplicationContext applicationContext) { SpringContextHolder.applicationContext = applicationContext; } //取得存儲(chǔ)在靜態(tài)變量中的ApplicationContext. public static ApplicationContext getApplicationContext() { checkApplicationContext(); return applicationContext; } //從靜態(tài)變量ApplicationContext中取得Bean, 自動(dòng)轉(zhuǎn)型為所賦值對(duì)象的類型. @SuppressWarnings("unchecked") public static <T> T getBean(String name) { checkApplicationContext(); return (T) applicationContext.getBean(name); } //從靜態(tài)變量ApplicationContext中取得Bean, 自動(dòng)轉(zhuǎn)型為所賦值對(duì)象的類型. //如果有多個(gè)Bean符合Class, 取出第一個(gè). @SuppressWarnings("unchecked") public static <T> T getBean(Class<T> clazz) { checkApplicationContext(); @SuppressWarnings("rawtypes") Map beanMaps = applicationContext.getBeansOfType(clazz); if (beanMaps != null && !beanMaps.isEmpty()) { return (T) beanMaps.values().iterator().next(); } else { return null; } } private static void checkApplicationContext() { if (applicationContext == null) { throw new IllegalStateException("applicaitonContext未注入,請(qǐng)?jiān)赼pplicationContext.xml中定義SpringContextHolder"); } } public static HttpServletRequest getRequest() { try { return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); } catch (Exception e) { return null; } } }
調(diào)用方法:
RedisUtil redisUtil= (RedisUtil) SpringContextHolder.getBean(RedisUtil.class);
結(jié)語
到此這篇關(guān)于SpringBoot靜態(tài)方法調(diào)用Spring容器bean的三種方案的文章就介紹到這了,更多相關(guān)SpringBoot靜態(tài)方法調(diào)用bean內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
swagger的請(qǐng)求參數(shù)不顯示,@Apimodel的坑點(diǎn)及解決
這篇文章主要介紹了swagger的請(qǐng)求參數(shù)不顯示,@Apimodel的坑點(diǎn)及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11java 日期各種格式之間的相互轉(zhuǎn)換實(shí)例代碼
這篇文章主要介紹了java 日期各種格式之間的相互轉(zhuǎn)換實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-02-02使用@Autowired 注入RedisTemplate報(bào)錯(cuò)的問題及解決
這篇文章主要介紹了使用@Autowired 注入RedisTemplate報(bào)錯(cuò)的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08如何理解Java中基類子對(duì)象的構(gòu)建過程從"基類向外"進(jìn)行擴(kuò)散的?
今天小編就為大家分享一篇關(guān)于如何理解Java中基類子對(duì)象的構(gòu)建過程從"基類向外"進(jìn)行擴(kuò)散的?,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-04-04springboot 返回json格式數(shù)據(jù)時(shí)間格式配置方式
這篇文章主要介紹了springboot 返回json格式數(shù)據(jù)時(shí)間格式配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11java集成開發(fā)SpringBoot生成接口文檔示例實(shí)現(xiàn)
這篇文章主要為大家介紹了java集成開發(fā)SpringBoot如何生成接口文檔的示例實(shí)現(xiàn)過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10詳解JavaWeb如何實(shí)現(xiàn)文件上傳和下載功能
這篇文章主要介紹了如何利用JavaWeb實(shí)現(xiàn)文件的上傳和下載功能,文中的示例代碼講解詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定的幫助,感興趣的小伙伴可以學(xué)習(xí)一下2021-12-12