java靜態(tài)方法里使用spring的注入對象方式
@Resource 導(dǎo)入應(yīng)用場景
大家都知道,Java靜態(tài)資源(靜態(tài)代碼塊,靜態(tài)方法,靜態(tài)屬性)在類加載的時(shí)候進(jìn)行加載,那么加載時(shí)機(jī)肯定是在spring對象注入之前的,所以我們在調(diào)用實(shí)際的靜態(tài)方法時(shí)就會(huì)出現(xiàn)空指針。
這種可能在實(shí)際開發(fā)中出現(xiàn)在我們的util工具類中.
IDEA編譯報(bào)錯(cuò)原因
- 靜態(tài)方法里邊引用了非靜態(tài)變量 distributeIdClient,這個(gè)會(huì)直接報(bào)錯(cuò)的

* 應(yīng)該不會(huì)有人認(rèn)為在注入上面加 static 就不會(huì)報(bào)錯(cuò)了吧. QAQ,
- 靜態(tài)方法中引用的 distributeIdClient 雖然用了@Resource注解,但是該注解的注入是在靜態(tài)方法加載之后執(zhí)行的,所以此處的 distributeIdClient 在使用時(shí)為null
- 當(dāng)一個(gè)類包含了@Resource的子類時(shí),他就必須交給spring來處理而不能使用new來初始化,否則會(huì)導(dǎo)致他的自動(dòng)裝配的子類為null。所以如果使用注解的方式,那么我們這個(gè)IdWorkerUtils類就需要加上@component注解來交給spring進(jìn)行初始化
解決方案
使用PostConstruct注解 PostConstruct 標(biāo)注方法執(zhí)行時(shí)機(jī)
完成依賴注入以執(zhí)行任何初始化之后,在類投入服務(wù)之前調(diào)用, 即: 在spring項(xiàng)目中,在一個(gè)bean的初始化過程中,方法執(zhí)行先后順序?yàn)?/p>
- Constructor > @Autowired > @PostConstruct
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
/**
* @description: id工具類
* @author: 單人影
* @create: 2022-09-15 14:04
**/
@Component
@Slf4j
public class IdWorkerUtils {
private static IdWorkerUtils utils;
@Resource
private DistributeIdClient distributeIdClient;
@PostConstruct
public void init() {
utils = this;
utils.distributeIdClient = this.distributeIdClient;
}
public static String getId() {
try {
Result<String> result = utils.distributeIdClient.stringNum();
log.info("請求id服務(wù)獲取請求id,響應(yīng)結(jié)果:{}", JacksonUtil.objectToString(result));
if (result != null && result.getIsSuccess() && StringUtils.isNotEmpty(result.getData())) {
return result.getData();
}
} catch (Exception e) {
log.warn("請求id服務(wù)獲取請求id 異常", e);
}
return IdWorker.getIdStr();
}
}
在靜態(tài)方法中 使用@value注解的值
@Component
public class XmlUtils {
//@Value只能給普通變量注入值,不能給靜態(tài)變量賦值,不能直接在這里寫@Value,這些直接注入就是null
@Value("${xml.encoded:UTF-8}")
public static String xmlEncoded;
}
解決辦法
/**
* @description: xml utils
* @author: 單人影
* @create: 2022-10-12 10:23
**/
@Slf4j
@Component
public class XmlUtils {
private static String xmlEncoded;
public String getXmlEncoded() {
return xmlEncoded;
}
// 注意: 構(gòu)造方法不能 是static 的
@Value("${xml.encoded:UTF-8}")
public void setXmlEncoded(String xmlEncoded) {
XmlUtils.xmlEncoded = xmlEncoded;
}
/**
* @Description: 將 xml 字符串轉(zhuǎn)換成對象
* @Param: [xmlText, clazz]
* @return: T
* @Author: 單人影
* @Date: 2022/10/12 10:24
*/
public static <T> T parseXmlStringToObj(String xmlText, Class<T> clazz) {
return JAXB.unmarshal(new StringReader(xmlText.trim()), clazz);
}
/**
* 將對象轉(zhuǎn)換成 xml 字符串
*
* @param obj 對象
* @param clazz 對象的類型
* @return xml 字符串
*/
public static <T> String parseObjToXmlString(T obj, Class<T> clazz) {
String result = StringUtils.EMPTY;
try {
JAXBContext jaxbContext = JAXBContext.newInstance(obj.getClass());
Marshaller marshaller = jaxbContext.createMarshaller();
// 格式化輸出
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// 編碼格式
marshaller.setProperty(Marshaller.JAXB_ENCODING, xmlEncoded);
// 去掉默認(rèn)報(bào)文頭
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
// 不進(jìn)行轉(zhuǎn)義字符的處理
marshaller.setProperty(CharacterEscapeHandler.class.getName(), (CharacterEscapeHandler) (ch, start, length, isAttVal, writer) -> writer.write(ch, start, length));
StringWriter writer = new StringWriter();
// 將對象轉(zhuǎn)換成 xml 字符串,存入 writer 中
marshaller.marshal(obj, writer);
result = writer.toString();
} catch (JAXBException e) {
log.error("將對象轉(zhuǎn)換成xml字符串失敗", e);
}
if (StringUtils.isEmpty(result)) {
throw new RuntimeException(String.format("將 【%s】 類型的對象轉(zhuǎn)換成 xml 文本失敗", clazz.getName()));
}
return result;
}
}
方案解釋
static的變量是歸屬于Class的,而Spring容器上下文只對Java對象進(jìn)行管理,Spring不鼓勵(lì)對static變量做注入Bean的操作,因此如果需要在某些工具類中將Bean賦值給靜態(tài)變量,可以使用構(gòu)造注入的方式. 或者使用@PostConstruct作為橋梁 同@resource. 或者 實(shí)現(xiàn) InitializingBean 重寫 afterPropertiesSet 實(shí)現(xiàn)給靜態(tài)類 賦值
// afterPropertiesSet 示例 容器初始化的時(shí)候給靜態(tài)屬性賦值
@Component
public class XmlUtils implements InitializingBean{
public static String XML_ENCODED;
@Value("${xml.encoded:UTF-8}")
public String xmlEncoded;
@Override
public void afterPropertiesSet() throws Exception {
XML_ENCODED= xmlEncoded;
}
}
調(diào)用過程:@Comment組件在springboot啟動(dòng)的時(shí)候就被掃描到,并且@Value實(shí)現(xiàn)注入,相當(dāng)于將xmlEncoded獲取到的值傳給工具類中的屬性,因此可以在工具類中,直接調(diào)用這個(gè)類的屬性,獲取到@Value取到的值。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Java 單元測試之Mockito 模擬靜態(tài)方法與私有方法最佳實(shí)踐
- Java中Integer類常用靜態(tài)方法實(shí)例詳解
- Java報(bào)錯(cuò):無法從靜態(tài)上下文中引用非靜態(tài)方法的解決方案
- java工具類static靜態(tài)方法讀取yml配置過程
- java的靜態(tài)方法調(diào)用方式
- 在非Spring管理對象中注入Spring Bean的解決方案
- SpringBoot注入靜態(tài)屬性或靜態(tài)對象的方法
- Spring實(shí)現(xiàn)對象注入的三種方法詳解
- Spring使用注解進(jìn)行對象注入的示例詳解
相關(guān)文章
SpringBoot3配置Logback日志滾動(dòng)文件的方法
本文介紹了在SpringBoot3中配置Logback日志滾動(dòng)文件的方法,因?yàn)镾pringBoot3內(nèi)置的logback版本是1.4.14,之前使用SpringBoot2.1.5的logback配置發(fā)現(xiàn)有些東西不能生效了,需要的朋友可以參考下2024-08-08
Spring AI Alibaba接入大模型時(shí)的依賴問題小結(jié)
文章介紹了如何在pom.xml文件中配置SpringAI Alibaba依賴,并提供了一個(gè)示例pom.xml文件,同時(shí),建議將Maven倉庫鏡像設(shè)置為阿里云以提高下載速度,具體配置方法跟隨小編一起學(xué)習(xí)下吧2025-02-02
SpringBoot利用@Validated注解優(yōu)雅實(shí)現(xiàn)參數(shù)校驗(yàn)
在開發(fā) Web 應(yīng)用時(shí),用戶輸入的合法性校驗(yàn)是保障系統(tǒng)穩(wěn)定性的基礎(chǔ),?Spring Boot 的 @Validated 注解 提供了一種更優(yōu)雅的解決方案,下面就跟隨小編一起學(xué)習(xí)一下吧2025-04-04
Intellij?IDEA根據(jù)maven依賴名查找它是哪個(gè)pom.xml引入的(圖文詳解)
這篇文章主要介紹了Intellij?IDEA根據(jù)maven依賴名查找它是哪個(gè)pom.xml引入的,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
Java 中的 BufferedReader 介紹_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
BufferedReader 是緩沖字符輸入流。它繼承于Reader。接下來通過本文給大家介紹BufferedReader的相關(guān)知識(shí),需要的朋友參考下吧2017-05-05

