在项目中引入redis做缓存策略时,往过滤器中引入RedisTemplate redisTemplate;一直报空指针异常。

由于之前一直是在controller,service,dao做@Autowired引入的,从未发生过类似的问题,所以起初猜测可能是jar包有问题,后面排除了这个原因。

导致@Autowired失效的原因大致有两个

1.SpringBoot项目的Bean装配默认规则是根据Application类所在的包位置从上往下扫描!

“Application类”是指SpringBoot项目入口类。这个类的位置很关键:

如果Application类所在的包为:com.root.app,则只会扫描com.root.app包及其所有子包,如果service或dao所在包不在com.root.app及其子包下,则不会被扫描!

即, 把Application类放到dao、service所在包的上级,com.root.Application

我出问题的类确实在Application类子包下面,排除此项。

2.意识到只是拦截器(或过滤器)上会有这样的问题,查询原因应该是:
拦截器执行在自动bean初始化之前导致这个问题的。

造成null的原因是因为拦截器加载是在springcontext创建之前完成的,所以在拦截器中注入实体自然就为null。

注入为null的时候,是通过new的方式创建的拦截器,通过new出来的实例是没有交给spring进行管理的,没有被spring管理的实例,spring是无法自动注入bean的,所以为null

解决方案

可以在过滤器中添加一下代码

    /**
     * 由于在过滤器中无法直接通过Autowired获取Bean,因此需要通过spring上下文来获取IOC管理的实体类
     * 此处主要是用于  RedisUserUtils
     * @param clazz
     * @param request
     * @param <T>
     * @return
     */
    public <T> T getBean(Class<T> clazz, HttpServletRequest request){
        WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        return applicationContext.getBean(clazz);
    }

 

然后在需要用到的方法中添加以下代码:request 可以在方法的参数中声明。

RedisUserUtils redisUtils =getBean(RedisUserUtils.class, request);

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐