訊息佇列監聽器無法注入bean的問題解決
阿新 • • 發佈:2019-01-30
在使用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
messageListener裡面呼叫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"); } } }
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;// 處理失敗, 也不重新處理 } }