本人在实习的过程中,一个项目功能需要在Listener中的handlerMessage(即Listener的监听响应方法)用到Service,但是出现了以下的问题:
如果使用Spring的@Autowired自动注入,会出现这个Service为空的异常。
即在这里使用Service的时候不可以使用注解注入的方式,究其原因,因为Listener是一个Servlet,而使用注解注入的必须是Spring的组件,故注解不能为Servlet中的对象注入,但是必须还需要使用到这个Service来调用dao对象来与数据库交互,于是查了一下资料,这里分享一个解决办法。
之前采用的注解注入的方式是这样的。(不论是@Autowired自动注入还是@Resource利用名称注入都不可以)
public class PosListener{
@Autowired
private PosService posService;
public void handlerMessage(MessageVO message){......}
}
如果想要让Service不为空并且能够与Spring的组件交互,则需要使用Spring进行注入,但是还不能使用注解。在Servlet的生命周期中我们知道,在项目启动的时候,会对Servlet进行一次初始化,我们可不可以在Servlet初始化的时候,利用Spring的配置文件进行注入?
所以修改后的代码如下:
public class PosListener implements ServletContextListener{
private PosService posService;
@Override
public void contextInitialized(ServletContextEvent sce) {
cvsPosService = WebApplicationContextUtils
.getWebApplicationContext(sce.getServletContext())
.getBean(PosServiceImpl.class);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
public void handlerMessage(MessageVO message){......}
}
这种方式,需要实现ServletContextListener,进而实现它的两个方法,contextInitialized和contextDestroyed,在contextInitialized中使用Spring的配置文件进行注入,这种方式,可以保证Service对象只被注入1次,而不会重复加载配置文件,除此之外,还需要在web.xml中将这个(PosListener)配置上。
但是,在handlerMessage中使用这个Service对象时,依然出现了空指针异常,这就有点不科学了,于是我接着排查,通过从头思考handlerMessage的工作流程,我发现,handlerMessage这个监听方法(即listener的event方法),每次从message queue中取得一个消息message,就会调用这个方法,因此,如果我们想要在事件监听方法event中使用Service方法,我们需要将想使用到的Service定义为static,才可以正常运行。