一、背景
1.今天寫代碼發現有一個使用@Component注解的util類,類中的方法都是static靜態修飾的,但是我要修改其中一個靜態方法,在靜態方法中我要調用一個service類,代碼如下
修改前:
@Component
@Slf4j
public class TestUtil {
private static final String CARRIER_MANDATORY_JOB_ID_LIST_CONFIG_NAME = "test";
public static List<Integer> get() {
return Lion.getList(CARRIER_MANDATORY_JOB_ID_LIST_CONFIG_NAME, Integer.class, ImmutableList.of(2, 5, 7, 14, 16));
}
}
修改后
@Component
@Slf4j
public class TestUtil {
private static final String CARRIER_MANDATORY_JOB_ID_LIST_CONFIG_NAME = "test";
private static final String SWITCH = "switch";
@Autowired
private static JobNeedCarrierQuery jobNeedCarrierQuery;
public static List<Integer> get() {
if(Lion.getBooleanValue(SWITCH)) {
return jobNeedCarrierQuery.doQuery();
}else {
return Lion.getList(CARRIER_MANDATORY_JOB_ID_LIST_CONFIG_NAME, Integer.class, ImmutableList.of(2, 5, 7, 14, 16));
}
}
}
二、問題
當執行修改后的代碼后,發現報了空指針異常,debug發現jobNeedCarrierQuery沒有被注入對象,調用doQuery方法是報NPE
三、原因
在 Java 中,針對 static 靜態成員,我們有一些最基本的常識:靜態變量(成員)它是屬於類的,而非屬於實例對象的屬性;同樣的靜態方法也是屬於類的,普通方法(實例方法)才屬於對象。而 Spring 容器管理的都是實例對象,包括它的@Autowired依賴注入的均是容器內的對象實例,所以對於 static 成員是不能直接使用@Autowired注入的。這很容易理解:類成員的初始化較早,並不需要依賴實例的創建,所以這個時候 Spring 容器可能都還沒“出生”,談何依賴注入呢?
四、解決方案
2.@PostConstruct方式實現
@Component (1)
@Slf4j
public class TestUtil {
private static final String CARRIER_MANDATORY_JOB_ID_LIST_CONFIG_NAME = "test";
private static final String SWITCH = "switch";
@Autowired. (2)
private JobNeedCarrierQuery jobNeedCarrierQuery;
private static TestUtil testUtil; (3)
@PostConstruct (4)
public void init(){
testUtil = this;
testUtil.jobNeedCarrierQuery = this.jobNeedCarrierQuery;
}
public static List<Integer> get() {
if(Lion.getBooleanValue(SWITCH)) {
return testUtil.jobNeedCarrierQuery.doQuery(BusinessLineEnum.SPOCK_BIKE.getCode()); (5)
}else {
return Lion.getList(CARRIER_MANDATORY_JOB_ID_LIST_CONFIG_NAME, Integer.class, ImmutableList.of(2, 5, 7, 14, 16));
}
}
}
3.set方法上添加@Autowired注解,類定義上添加@Component注解
@Component
public class TestUtil {
private static final String CARRIER_MANDATORY_JOB_ID_LIST_CONFIG_NAME = "test";
private static final String SWITCH = "switch";
private static JobNeedCarrierQuery jobNeedCarrierQuery;
@Autowired
public void setDatastore(JobNeedCarrierQuery jobNeedCarrierQuery) {
TestUtil.jobNeedCarrierQuery=jobNeedCarrierQuery;
}
public static List<Integer> get() { if(Lion.getBooleanValue(SWITCH)) { return jobNeedCarrierQuery.doQuery(); }else { return Lion.getList(CARRIER_MANDATORY_JOB_ID_LIST_CONFIG_NAME, Integer.class, ImmutableList.of(2, 5, 7, 14, 16)); } }
}
