Spring踩坑:@Autowired自动注入service/dao为null,在listener中调用service, listener和servlet的加载先后顺序

原因:@Autowired自动注入service/dao为null,原因是因为在listener中调用了service,然而 listener比servlet先加载,所以listener加载完了的时候,servlet还没加载出来,所以Autowired为null。

解决办法:手动获取bean,不要自动注入。

详细内容请继续往下看,解决方案请跳到最后。

背景介绍

本来只是个普通的java web项目,功能是:实现MessageListener类,在onMessage()方法中,订阅amq的数据,并通过websocket推送到前端。

后来功能延展,需要和数据库做交互。

所以需要在onMessage()方法中,额外增加一条将收到的数据写入数据库。

实现逻辑

  1. 引入了spring springmvc mybatis,注意mybatis jar包和mybatis-spring jar包要兼容,mybatis-3.4是不能和mybatis-spring-1.2兼容的。

2.配置web.xml,applicationContext.xml,springmvc-servlet.xml,注意下路径别写错了

3.写service,写dao的接口和xml

3.在实现MessageListener的类中,@Autowired一个service,service再@AutoWired一个dao。

注意一下,service可以手动实例化,就是new 一个service出来。
但是普通的spring项目不要这样做,因为手动new出来的service,不归spring管,在service里面@Autowired的dao,spring就不会帮我们自动注入了。
还是得从容器里面拿,
@AutoWired
Service service;

错误原因

就是写在开头的,加载顺序问题。

我在listener中调用了service,我需要的加载顺序是:servlet先加载,listener后加载。

但实际上加载的顺序是按web.xml来的:context-param --> listeners --> filters --> servlets

所以我在Listener中自动注入service,servlet还没加载呢,因此AutoWired的对象是null。

解决方案

这时候就不用自动注入了,手动获取吧。

service就直接在初始化的时候全局new一个吧,这样也可以的,主要是dao的接口实例化。
先全局一个MyDao myDao

if (myDao == null) {
    ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    myDao = ac.getBean(MyDao.class);
}

注意路径不要写错了哦,要写classpath下的路径。

问题到这里就解决啦,脑壳大,喝杯奶茶庆祝一下。

posted on 2022-01-12 11:01  northwest  阅读(1068)  评论(0编辑  收藏  举报

导航