1. 程式人生 > >訊息佇列監聽器無法注入bean的問題解決

訊息佇列監聽器無法注入bean的問題解決

在使用ActiveMq或者其他訊息佇列的過程中,第一步對ActiveMq進行初始化的過程是放在ContextListener的初始化的時候的;

然而當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註解的類的小寫全稱。

下面給出我的程式碼例子:

SpringContextHolder
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class SpringContextHolder implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    /**
     * 實現ApplicationContextAware介面的context注入函式, 將其存入靜態變數.
     */
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextHolder.applicationContext = applicationContext; // NOSONAR
    }

    /**
     * 取得儲存在靜態變數中的ApplicationContext.
     */
    public static ApplicationContext getApplicationContext() {
        checkApplicationContext();
        return applicationContext;
    }

    /**
     * 從靜態變數ApplicationContext中取得Bean, 自動轉型為所賦值物件的型別.
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        checkApplicationContext();
        return (T) applicationContext.getBean(name);
    }

    /**
     * 從靜態變數ApplicationContext中取得Bean, 自動轉型為所賦值物件的型別.
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(Class<T> clazz) {
        checkApplicationContext();
        return (T) applicationContext.getBeansOfType(clazz);
    }

    /**
     * 清除applicationContext靜態變數.
     */
    public static void cleanApplicationContext() {
        applicationContext = null;
    }

    private static void checkApplicationContext() {
        if (applicationContext == null) {
            throw new IllegalStateException("applicaitonContext未注入,請在applicationContext.xml中定義SpringContextHolder");
        }
    }
}
messageListener裡面呼叫
SpringContextHolder.getBean("messageDistribute");

public class WebMessageListener implements MessageListener {
    private static final Logger logger = LoggerFactory.getLogger(WebMessageListener.class);
    private static long callCount = 0;

//    @Autowired
//    private MessageDistribute messageDistribute;


    public Action consume(Message message, ConsumeContext context) {

        logger.info("consume: " + message);
        String topic = "";
        try {
            //do something..
            topic = message.getTopic();
            String content = new String(message.getBody(), "UTF-8");
            
//            Thread.sleep(1000);
            JSONObject resultjson = JSONObject.fromObject(content);
            //PushInfoBeanEx info = JSON.parseObject(content, PushInfoBeanEx.class);
            //PushServiceExImpl.getgPushFactory().sendMessageByMQ(info);
            //接收訊息

            //接收並處理訊息
            MessageDistribute mMessageDistribute =  SpringContextHolder.getBean("messageDistribute");
            mMessageDistribute.socketSendCallBack(Integer.parseInt(pushid),code,new Date());
            return Action.CommitMessage;
        } catch (Exception e) {
            //消費失敗
            return Action.CommitMessage;// 處理失敗, 也不重新處理
        }
    }