问题
在SpringBoot中,需要使用@Autowired
注解注入static
静态变量,但是此种用法会报空指针异常。
问题重现
HelloWorld输出Demo
@Autowired注入static静态变量
运行空指针异常
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.langjialing.controller.HelloController.Hello()" because "com.langjialing.DemoApplication.helloController" is null
at com.langjialing.DemoApplication.main(DemoApplication.java:17)
解决
原因
表面原因:静态变量是属于类本身的信息,当类加载器加载静态变量时,Spring的上下文环境还没有被加载,所以不可能为静态变量绑定值(这只是最表象原因,并不准确)。同时,Spring也不鼓励为静态变量注入值(言外之意:并不是不能注入),因为它认为这会增加了耦合度,对测试不友好。
真实原因:扫描Class类需要注入的元数据的时候,直接选择忽略掉了static成员(包括属性和方法)。
博主水平有限,更深层次的原因建议移步他处。
HelloWorld输出Demo
HelloWorld输出的Controller不变。
解决方式一:set方法注入
private static HelloController helloController;
@Autowired
public void setHelloController(HelloController helloController){
DemoApplication.helloController = helloController;
//这里也可以使用:this.helloController = helloController;
}
正常输出结果
解决方式二:构造器注入
private static HelloController helloController;
public DemoApplication(HelloController helloController) {
DemoApplication.helloController =helloController;
//这里也可以使用:this.helloController =helloController;
}
正常输出结果
解决方式三:@PostConstruct注解
使用@PostConstruct
注解,在里面为static静态成员赋值。
private static HelloController helloController;
@Autowired
ApplicationContext applicationContext;
@PostConstruct
public void init() {
DemoApplication.helloController = applicationContext.getBean(HelloController.class);
}
正常输出结果
总结
变量方式注入应该尽量避免,使用set方法注入或者构造器注入,这两种方式的选择就要看这个类是强制依赖的话就用构造器方式,选择依赖的话就用set方法注入。