2

在我的 Spring 项目中,我确实有一个由 spring 管理的 JMS 消息侦听器:

<bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory" p:brokerURL="tcp://localhost:61616"/>

<bean id="simpleExampleListener" class="my.package.ExampleListener" />

<jms:listener-container container-type="default" connection-factory="jmsFactory" acknowledge="auto" concurrency="1-3">
    <jms:listener destination="TEST.FOO" ref="simpleExampleListener" method="onMessage"/>
</jms:listener-container>

在一个特定的消息上,我需要调用一个 Spring MVC 控制器,它是请求范围的(实际上目标是调用一个服务,它也是请求范围的并被控制器调用)。因此,我不能直接从侦听器中执行此操作,因为 Spring 根据需要管理它们并且它们不受请求范围限制(因为我无法通过@Autowireor访问控制器ApplicationContext)。一种解决方案可能是通过我的控制器映射的带有 Rest Template 到 URL 的 HTTP 调用。但是,我认为这是一种开销,所以也许还有其他方法可以避免 HTTP 协议开销并在 Spring MVC 框架中调用 Controller?

4

1 回答 1

2

您需要质疑为什么将服务类定义为请求范围 - 理想情况下,服务层不应该对 Web 层有任何隐式/显式依赖。如果这不在您的控制范围内,您可以使用以下解决方法。您将需要添加 spring-test.jar 作为依赖项。

    class Listener {

    @Autowired
    RequestScopedService requestScopedService;


    void handle() {
        MockHttpServletRequest request = new MockHttpServletRequest();
        RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
        try {
             requestScopedService.callSomeMethod();
        } finally {
             ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).requestCompleted();
             RequestContextHolder.resetRequestAttributes();
        }

如果服务 bean 配置了<aop:scoped-proxy/>标签,那么它可以自动装配。否则,您需要获取应用程序上下文(通过实现 ApplicationContextAware)并进行查找。

于 2012-05-11T17:03:06.823 回答