先說結論: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層進行業務處理。