SpringBoot靜態(tài)方法調用Spring容器bean的三種解決方案
問題分析
今天一個小伙伴和我說@Autowired 注入的Bean為null值,經過一番溝通后,我發(fā)現(xiàn)原來他需要在靜態(tài)方法中調用容器Bean,大致將代碼貼出來給大家看看:
//模擬錯誤的使用方式
@Autowired
private static RedisUtil redisUtilBean;
public static String getMsgByRedis(){
redisUtilBean.get("xxx") //這里redisUtilBean一定會是NULL值
}
為什么會出現(xiàn)這種情況?原因是Spring容器的依賴注入是依賴set方法,而set方法是實例對象的方法,注入依賴時是無法注入靜態(tài)成員變量的,在調用的時候依賴的Bean才會為null;
解決方案一
使用@PostConstruct注解,
@Autowired
private RedisUtil redisUtilBean;
//由于靜態(tài)方法無法使用注入的Bean 定義靜態(tài)變量
private static RedisUtil redisUtil;
//當容器實例化當前受管Bean時@PostConstruct注解的方法會被自動觸發(fā),借此來實現(xiàn)靜態(tài)變量初始化
@PostConstruct
public void init(){
this.redisUtil = redisUtilBean;
}
public static String getMsgByRedis(){
redisUtil.get("xxx") //這里可以正常使用
}
解決方案二
利用springboot的啟動類中,SpringApplication.run() 方法返回的是一個ConfigurableApplicationContext對象通過定義static變量ConfigurableApplicationContext,利用容器的getBean方法獲得依賴對象;
@SpringBootApplication
@EnableTransactionManagement
public class Application {
//定義靜態(tài)的ApplicationContext
public static ConfigurableApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext = SpringApplication.run(Application.class, args);
}
}
//調用 注意Application是我們SpringBoot的啟動類
public static String getMsgByRedis(){
Application.applicationContext..getBean(RedisUtil .class).get("xxx")
}
解決方案三
在我們以前SpringMVC中常用的工具類,通過實現(xiàn)ApplicationContextAware接口,網上也很多這里就把工具類貼出來即可;
/*
* 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, 可在任何代碼任何地方任何時候中取出ApplicaitonContext.
*
* @author 李懷明
* @version 2017-01-02
*/
@Component
public class SpringContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
//實現(xiàn)ApplicationContextAware接口的context注入函數(shù), 將其存入靜態(tài)變量.
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextHolder.applicationContext = applicationContext;
}
//取得存儲在靜態(tài)變量中的ApplicationContext.
public static ApplicationContext getApplicationContext() {
checkApplicationContext();
return applicationContext;
}
//從靜態(tài)變量ApplicationContext中取得Bean, 自動轉型為所賦值對象的類型.
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
checkApplicationContext();
return (T) applicationContext.getBean(name);
}
//從靜態(tài)變量ApplicationContext中取得Bean, 自動轉型為所賦值對象的類型.
//如果有多個Bean符合Class, 取出第一個.
@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未注入,請在applicationContext.xml中定義SpringContextHolder");
}
}
public static HttpServletRequest getRequest() {
try {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
} catch (Exception e) {
return null;
}
}
}
調用方法:
RedisUtil redisUtil= (RedisUtil) SpringContextHolder.getBean(RedisUtil.class);
結語
到此這篇關于SpringBoot靜態(tài)方法調用Spring容器bean的三種方案的文章就介紹到這了,更多相關SpringBoot靜態(tài)方法調用bean內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
swagger的請求參數(shù)不顯示,@Apimodel的坑點及解決
這篇文章主要介紹了swagger的請求參數(shù)不顯示,@Apimodel的坑點及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11
使用@Autowired 注入RedisTemplate報錯的問題及解決
這篇文章主要介紹了使用@Autowired 注入RedisTemplate報錯的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
如何理解Java中基類子對象的構建過程從"基類向外"進行擴散的?
今天小編就為大家分享一篇關于如何理解Java中基類子對象的構建過程從"基類向外"進行擴散的?,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-04-04
springboot 返回json格式數(shù)據(jù)時間格式配置方式
這篇文章主要介紹了springboot 返回json格式數(shù)據(jù)時間格式配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
java集成開發(fā)SpringBoot生成接口文檔示例實現(xiàn)
這篇文章主要為大家介紹了java集成開發(fā)SpringBoot如何生成接口文檔的示例實現(xiàn)過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10

