在项目中引入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);
更多推荐