Spring:如何将 SimpMessagingTemplate bean 暴露给根上下文?

Spring : how to expose SimpMessagingTemplate bean to root context ?

我正在开发一个 Java webapp 以 Spring 作为主要框架(Spring 核心,Spring mvc,Spring 安全,Spring 数据,Spring websocket 被特别使用)。

像这样在 Spring 上下文中声明 message-broker 为上下文提供了一个 SimpMessagingTemplate bean:

<websocket:message-broker>
    <websocket:stomp-endpoint path="/stomp">
        <websocket:sockjs/>
    </websocket:stomp-endpoint>
    <websocket:simple-broker prefix="/topic,/queue"/>
</websocket:message-broker>

我必须将此标记放在 dispatcher-servlet.xml 中(而不是 applicationContext.xml),否则客户端在尝试连接到 websocket 时(在初始页面加载时)将收到 404。

但是,由于这个提供 SimpMessagingTemplate bean(向连接的客户端发送消息)的标签在根上下文中不可用,当服务(由根上下文扫描)发送 websocket 消息时, SimpMessagingTemplate bean 无法自动装配(经典 NoSuchBeanDefinitionException)。

以前,<websocket:message-broker> 标签在 applicationContext.xml 中,dispatcher-servlet.xml 正在导入 applicationContext.xml 并且一切正常 - 然而我惊讶地发现这是当我最近使用 SessionRegistry 修改任意用户会话时出错。

确实,由于 DispatcherServlet 显式导入了已经隐式继承的根上下文,SessionRegistry bean 被创建了两次,导致意外行为(SO 上有几篇文章描述这个常见错误,通常用户希望获得所有主体的列表,但由于 SessionRegistry bean 重复而得到空列表,并找出这一点)。

所以为了解决这个问题,我删除了

<import resource="applicationContext.xml"/>

来自调度员-servlet.xml,但从那以后:

这个可能相当普遍的问题的解决方案是什么? DispatcherServlet 可以从根上下文访问 bean,但反之亦然,那么我应该如何解决这个问题?

我找到了一个肮脏的解决方案。我不喜欢它,但鉴于缺少关于 SO 的答案(另请参阅: ),以及来自现任和前任同事的答案,我不得不继续该项目并实施了一个肮脏的修复。

肮脏的修复是 Autowire Controller 和 Scheduled 类 中的 SimpMessagingTemplate(全部由 dispatcher-servlet 扫描,其中声明 websocket tag ),并将 SimpMessagingTemplate 作为参数传递给服务方法(在 root context 中声明)。

此解决方案不透明(理想情况下 SimpMessagingTemplate 应该直接在服务中自动装配)但它确实解决了问题。