使用@Autowired注入static静态变量,空指针异常解决

郎家岭伯爵 2022年03月09日 743次浏览

问题

在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方法注入。