ActiveMQ监听器MessageListener中使用@Inject、@Autowired注入为空问题记录;
1.在使用ActiveMQ的过程中,有一个诡异的问题一直困扰着我,MessageListener监听器中代码,无规律出现空指针,分析代码多次未查到真正原因,自己几乎快要怀疑人生了!
public class SmsMtCodeListener implements MessageListener {
private static Logger logger = Logger
.getLogger(SmsMtCodeListener.class);
@Inject
private CodeProducerService mobileCodeProducerService;
@Inject
private CodeProducerService telecomCodeProducerService;
@Inject
private CodeProducerService unicomCodeProducerService;
@Inject
private SmsBpConfig externalBpConfig;
private static List<String> numh3s = new ArrayList<String>();
@Override
public void onMessage(Message message) {
...
}
2.坚信奇怪的现象背后一定会有必然的诱因,静下心来一步步调试,终于让我发现了一些蛛丝马迹(当事代码在上面):
当监听器MessageListener第一次收到消息的时候属性mobileCodeProducerService、telecomCodeProducerService、unicomCodeProducerService都能正常注入容器中对应对象,而后面部分收到消息mobileCodeProducerService、telecomCodeProducerService、unicomCodeProducerService居然都是为null. 真奇怪!发生啥了! what XX ! SmsMtCodeListener 难道不是同一个对象吗!联想到SmsMtCodeListener 是线程池控制!难道在线程中spring @Inject @Autowired无效!立即google搜索spring注解和线程相关话题!果然,spring限制了线程中@Autowired、@Inject 注入。按照现象来总结应该有如下原理:当线程池中有多个MessageListener 对象时,spring @Autowired、@Inject 只会对线程池中其中一个MessageListener 对象,注入属性!其他的MessageListener 对象均不能正常注入属性。
3.解决之道
既然都知道了问题所在,那问题就解决了一半了,解决方法如下:
建立一个能获取ApplicationContext的类,复写setApplicationContext方法,并在类上注@Componen,
这样spring容器在实例化AppContextHolder 的时候就能调用setApplicationContext方法,传入ApplicationContext 对象给我们;这样我们就可以欢快的AppContextHolder.getBean()了。具体代码如下:
@Component
public class AppContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
AppContextHolder.applicationContext = applicationContext;
}
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
public static <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
}
4.问题代码修改后
public class SmsMtCodeListener implements MessageListener {
private static Logger logger = Logger
.getLogger(SmsMtCodeListener.class);
private CodeProducerService mobileCodeProducerService;
private CodeProducerService telecomCodeProducerService;
private CodeProducerService unicomCodeProducerService;
private SmsBpConfig externalBpConfig;
private static List<String> numh3s = new ArrayList<String>();
private void initBean() {
mobileCodeProducerService = AppContextHolder
.<CodeProducerService>getBean("mobileCodeProducerService");
telecomCodeProducerService = AppContextHolder
.<CodeProducerService>getBean("telecomCodeProducerService");
unicomCodeProducerService = AppContextHolder
.<CodeProducerService>getBean("unicomCodeProducerService");
externalBpConfig = AppContextHolder
.<SmsBpConfig>getBean("externalBpConfig");
}
@Override
public void onMessage(Message message) {
initBean();
......
}
网友评论