继承ApplicationContextAware接口后报空指针NullPointerException异常

前言

曾经在简书上看过一篇博客说写博客时加个前言纯粹是在说废话,其实我觉得我现在确实在说废话,但是前言有一个作用可以让博主描绘此刻的心情,比如我现在解决了这个问题后内心千万只草泥马在奔腾,所以需要写个前言平复一下心情好缕清自己的思路
继承ApplicationContextAware接口后报空指针NullPointerException异常_第1张图片

工具类

首先我写了一个工具类继承ApplicationContextAware接口方便个别无法使用@Autowired注入的类注入spring容器中
工具类代码如下:

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author ZP
 * @date 2020/4/22.
 */
@Component
public class SpringUtil implements ApplicationContextAware {
     
    private static ApplicationContext applicationContext;

    // 获取applicationContext
    public static ApplicationContext getApplicationContext() {
     
        return applicationContext;
    }

    // 通过name获取 Bean.
    public static Object getBean(String name) {
     
        return getApplicationContext().getBean(name);
    }

    // 通过class获取Bean.
    public static <T> T getBean(Class<T> clazz) {
     
        return getApplicationContext().getBean(clazz);
    }

    // 通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name, Class<T> clazz) {
     
        return getApplicationContext().getBean(name, clazz);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
     
        if (SpringUtil.applicationContext == null) {
     
            SpringUtil.applicationContext = applicationContext;
        }
    }
}

其实在我写的demo里还是可以正常注入的,但是集成进系统后报错,最怕碰到这种迷惑bug,这边可以,那边不可以。最后通过两边的同时debug猜出问题所在。
比如我的报错在第27行

Caused by: java.lang.NullPointerException: null
	at com.zp.websocket.SpringUtil.getBean(SpringUtil.java:27) ~[classes/:na]
	at com.zp.websocket.MyWebSocket.(MyWebSocket.java:22) ~[classes/:na]
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_111]
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_111]
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_111]
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_111]
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:172) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	... 19 common frames omitted

这个是在demo成功注入情况下的debug截图
继承ApplicationContextAware接口后报空指针NullPointerException异常_第2张图片
这是系统失败注入情况下的debug截图
继承ApplicationContextAware接口后报空指针NullPointerException异常_第3张图片
显而易见,失败的原因是类内部的applicationContext没有被实例,所以我们到实例applicationContext的代码上并加上断点康康
这是成功的时候
继承ApplicationContextAware接口后报空指针NullPointerException异常_第4张图片
而失败的情况是哪怕打了断点但还没执行重写的setApplicationContext方法就抛出异常了,而我这个工具类只在MyWebSocket.java里用到,他们的位置如图
继承ApplicationContextAware接口后报空指针NullPointerException异常_第5张图片

是在同一个包下的,demo里的位置是
继承ApplicationContextAware接口后报空指针NullPointerException异常_第6张图片
在两个不同的包下,那么会不会是因为位置问题,spring启动时的加载类顺序问题,在同一个包下从上而下扫描,所以是先MyWebSocket再SpringUtil。为此我还特地做个试验,把SpringUtil改名为MySpringUtil使其在上面
继承ApplicationContextAware接口后报空指针NullPointerException异常_第7张图片
结果真的能执行到setApplicationContext并且没有抛异常
继承ApplicationContextAware接口后报空指针NullPointerException异常_第8张图片
好吧,真的是顺序问题,spring原本先注入我的MyWebSocket,因为我的MyWebSocket里用到了继承ApplicationContextAware的SpringUtil,而此时我的SpringUtil还没注入spring容器里最后导致空指针异常。解决方法就是改一下顺序,让SpringUtil先执行,这样继承ApplicationContextAware的setApplicationContext方法就会先执行确保applicationContext有实例对象,这样就能避免异常了。

你可能感兴趣的:(JavaWeb)