自己踩坑
在做web项目时,我们有时候需要在项目启动的时候需要做一些初始化的操作,例如:读取数据库数据放入redis缓存中,自己就是在这个地方碰到了问题,主要是自己对tomcat容器中的结构不熟悉,当时找了很多资料才解决了。
先看代码
public class LoadDbToRedisListener extends ContextLoaderListener {
@Autowired
private LoadDbToRedisService loadToRedisService;
/** 日志 */
private static final Logger LOG = LoggerFactory.getLogger(LoadDbToRedisListener.class);
/**
* 重写ContextLoaderListener的contextInitialized方法
* @param event 事件
*/
@Override
public void contextInitialized(ServletContextEvent event) {
super.contextInitialized(event);
try {
loadToRedisService.loadCodesToRedis();
}catch (Exception e){
LOG.info("数据库载入缓存失败" + e.toString());
}
}
}
一开始我使用了上面的代码,但是执行不成功数据存人redis失败,debug进来发现loadToRedisService对象是空。翻阅资料发现Listener对象的生命周期是由servlet容器管理的,加载的时候servlet容器并不认识@Autowired注解,因此造成对象为空,loadToRedisService对象的声明周期是由Srping容器管理。
解决
public class LoadDbToRedisListener extends ContextLoaderListener {
private static final Logger LOG = LoggerFactory.getLogger(LoadDbToRedisListener.class);
/**
* 重写ContextLoaderListener的contextInitialized方法
* @param event 事件
*/
@Override
public void contextInitialized(ServletContextEvent event) {
super.contextInitialized(event);
try {
LoadDbToRedisService loadToRedisService = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext()).getBean(LoadDbToRedisServiceImpl.class);
loadToRedisService.loadCodesToRedis();
}catch (Exception e){
LOG.info("数据库载入缓存失败" + e.toString());
}
}
}
使用WebApplicationContextUtils工具类引入loadToRedisService对象成功,该工具类的作用是获取到spring容器的引用。
但是要注意的一点是该Listener初始化时要确保spring中的对象已经加载完成,否则同样会造成空指针。需要在web.xml文件中先配置初始化spring容器的Listener,然后在配置自己的Listener。
最后还要说明:在web Server容器中,无论是Servlet,Filter,还是Listener都不是Spring容器管理的,因此我们都无法在这些类中直接使用Spring注解的方式来注入我们需要的对象。