如何指示 spring 实例化消息侦听器容器?

How do I instruct spring to instantiate message listener containers?

我正在使用 Spring 4.2.3 和 Java 1.7

我有单元测试

@ContextConfiguration(classes = TestConfiguration.class)
public class TestJmsListener extends AbstractTestNGSpringContextTests {

    @Autowired
    private JmsMessagingTemplate jmsTemplate;

    @Autowired
    @Qualifier("destination")
    private Destination destination;

    @Test
    public void test() {
        assert(jmsTemplate.convertSendAndReceive(destination, "test", Boolean.class));
    }

}

测试调用 TestConfiguration class,但实际上只是扩展了以下配置。在 TestConfiguration 中,我只是重写了 connectionFactory,以便它实例化一个嵌入式 activemq 代理。

@Configuration
@EnableJms
@ComponentScan("messaging")
@PropertySource(value = "classpath:messaging.properties")
public class CommonMessagingConfiguration {

    // bunch of beans, connection factories, destinations, etc

    @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        factory.setConcurrency("10");
        return factory;
    }

}

测试执行,在日志中我可以看到为我的 "test" 消息创建了一个队列。消息在队列中挂起,但是,队列中没有消费者。这是我的监听器实现:

@Component
public class JmsExampleListener {

    @JmsListener(containerFactory = "jmsListenerContainerFactory",
            destination = "${messaging.destinations.example}")
    public boolean listen(String message) {
        return message != null;
    }
}

当我将调试器附加到 DefaultJmsListenerContainerFactory#createContainerInstance() 时,我注意到它曾经被命中。但是,当我将一个附加到 JmsListenerAnnotationBeanPostProcessor#postProcessAfterInitialization 时,它到达了那个断点,我可以看到 spring 正在检测我的组件。 Spring 实例化它并向它的内部注册器注册该实例(正如我所期望的那样)。

问题似乎是从未为注册的端点创建容器。我尝试遵循 Spring example 但是,它们没有提供任何见解。

我注意到的一件事是 Listener post 处理器有一个内部注册器并且有一个内部 属性 startImmediately 这是错误的。它似乎扩展了 InitializingBean 并因此将开始 属性 设置为 true ,我认为这将开始启动容器......但是,这不会发生。事实上,如果我在 afterPropertiesSet 上放置一个断点,它永远不会被调用。我假设是因为 post 处理器中的实例不是 spring 托管 bean。

有没有人尝试过与我正在做的类似的事情并且遇到了同样的问题?

更新

经过进一步调查,@EnableJms 实例化的 JmsListenerAnnotationBeanPostProcessor 似乎没有在配置容器后调用 afterSingletonsInstantiated。上述方法中的逻辑负责为所有已注册端点构造 MessageListenerContainer。为什么 afterSingletonsInstantiated 不会被调用?应用程序上下文不应该自动调用它吗?

事实证明,我有一个项目依赖项导致 spring-context 源成为版本 4.0.9。在我解决了冲突并有效地加载了 4.2.3 中的 AbstractApplicationContext 之后,组件开始工作了。