消息队列监听器无法注入bean的问题解决

本文探讨了在使用Spring框架时遇到的一个常见问题——如何解决因Spring容器扫描顺序导致的依赖注入失败。通过实例介绍了如何利用SpringContextHolder和ApplicationContextAware来正确获取Spring管理的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;// 处理失败, 也不重新处理
        }
    }



评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值