ActiveMQ监听器MessageListener中使用@Inject、@Autowired注入为空

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 numh3s = new ArrayList();

    @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 getBean(Class clazz) {
        return applicationContext.getBean(clazz);
    }

    public static  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 numh3s = new ArrayList();


    private void initBean() {
        mobileCodeProducerService = AppContextHolder
                .getBean("mobileCodeProducerService");
        telecomCodeProducerService = AppContextHolder
                .getBean("telecomCodeProducerService");
        unicomCodeProducerService = AppContextHolder
                .getBean("unicomCodeProducerService");
        externalBpConfig = AppContextHolder
                .getBean("externalBpConfig");
    }

    @Override
    public void onMessage(Message message) {
        initBean();
......
}

你可能感兴趣的:(ActiveMQ监听器MessageListener中使用@Inject、@Autowired注入为空)