一、背景
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)); } }
}