先说结论: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层进行业务处理。