先说结论:Spring容器还没有加载完Bean,你就去调用了!
一般的注解没加,bean的名字写错都好检查,但是逻辑错误就需要看清自己的思维过程了。
实例:在使用ActiveMq的过程中,第一步对ActiveMq进行初始化的过程是放在ContextListener的初始化的时候的,代码如下:
public class ContextListener implements ServletContextListener
{
@Autowired
MqManageService manageService;
public void contextDestroyed(ServletContextEvent arg0) { System.out.print("contextDestroyed"); } public void contextInitialized(ServletContextEvent arg0) { System.out.print("contextInitialized"); String MQNAME = ""; InitConfig initConfig = new InitConfig(); initConfig.init(); MQNAME = InitConfig.confCache.get(Constants.MQNAME).toString(); ActiveMQUtil.getInstance().receive("queue://" + MQNAME, new MessageListener() { @Override public void onMessage(Message msg) { try { //MqManageService manageService = new MqManageService(); ResultPojo pojo = manageService.getMqMsg(msg); if(!pojo.getappCode().equals("0")){ LoggerHelper.LOG.error("接收失败"+pojo.getResultList()); } } catch (Exception e) { LoggerHelper.LOG.error(e); } } }); } }
然而当mq接收到消息的时候触发getMqMsg方法的时候报错null,调试发现MqManageService根本没有获取到,我的想法是获取的方式不对,@Autowired这种方式获取bean不成功,但是bean肯定是已经存在于spring容器中的,如果对思维理解熟悉的人已经知道我的问题出在哪里了,没错,此时,spring容器中根本没有完成对注解bean的扫描,因为dispatcher.xml中配置的注解bean的优先级肯定没有框架中的contextListener的优先级高,contextListener初始化的时候根据@Autowired进行扫描的话,肯定是null的呀!
当我使用new对象的时候确实可以成功获取到这个MqmanageService,但是其调用的service(也是注解方式的)又获取不到了,原因是一样的。那么我可不可以在这里也new一个对象出来呢?可以是可以,但是没有意义,因为通过注解方式注册到容器中的bean本身就是单例模式,再new一个出来,违背初衷。还有一种方式就是可以通过ApplicationContextAware来getBean,这里的Bean的name就是@Service注解的类的小写全称。
所以啊,思维有漏洞,当我思考推理的时候应该看看哪一步是假设的,没有依据的假设就是错误的根源。徐总真厉害,多问,不要怕啊哈哈。
ps:上面的代码设计有问题,在ContextListener初始化的时候只需要将MQ初始化就可以了,不需要在此直接调用接口或者Queue将消息传递出去,用线程循环接收出去传到core层进行业务处理。