Spring Messaging でのWebSocketメモ
Spring MessagingでのSTOMPは以下の形で設定を行う。 これがなぜ動くのかを軽く探ってみたのでメモとして残しておく。
普通にSpringでWebsocketを使いたいならリファレンスのここ見ればよいかと。
なぜこのリファレンスにあるソースが動くのかを大まかに調べるためにこの記事にメモしておく。
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/portfolio").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.setApplicationDestinationPrefixes("/app"); config.enableSimpleBroker("/topic", "/queue"); } }
アノテーション、@EnableWebSocketMessageBrokeには以下のアノテーションが付けられている
... @Import({ DelegatingWebSocketMessageBrokerConfiguration.class }) public @interface EnableWebSocketMessageBroker { }
DelegatingWebSocketMessageBrokerConfigurationが渡されている。
DelegatingWebSocketMessageBrokerConfigurationの中身
InjectionされたWebScoketMessageBrokerConfigurerのリストに対して 処理を移譲する形になっている。
親クラスWebSocketMessageBrokerConfigurationSupportにて
SimpAnnotationMethodMessageHandlerを返却するcreateAnnotationMethodMessageHandlerが実装されている。
このメソッド内部ではWebSocketAnnotationMethodMessageHandlerがインスタンス化されて返却されている。
このメソッドはAbstractMessageBrokerConfigurationのsimpAnnotationMethodMessageHandlerから呼び出される。
WebSocketAnnotationMethodMessageHandlerはSimpAnnotationMethodMessageHandlerの子クラスである。
SimpAnnotationMethodMessageHandlerにはinitReturnValueHandlersというメソッドが実装されており
これはこの親クラスのAbstractMethodMessageHandler
また、このクラスAbstractMethodMessageHandler
afterPropertySetメソッドはInitializingBeanで定義されているメソッドである。
話を元に戻して、先ほどのSimpAnnotationMethodMessageHandlerのinitReturnValueHandlersではSendToMethodReturnValueHandlerとSubscriptionMethodReturnValueHandlerと
その他のHandlerMethodReturnValueHandlerを実装しているクラスのリストを返却している。
HandlerMethodReturnValueHandlerは以下のようなインターフェースになっている。
package org.springframework.messaging.handler.invocation; import org.springframework.core.MethodParameter; import org.springframework.messaging.Message; public interface HandlerMethodReturnValueHandler { boolean supportsReturnType(MethodParameter arg0); void handleReturnValue(Object returnValue, MethodParameter returnType, Message<?> message) throws Exception; }
この実装の参考はSendToMethodReturnValueHandlerを見るとよいかと思われる。
HandlerMethodReturnValueHandlerのhandleReturnValueが呼ばれる個所
AbstractMethodMessageHandler
このクラスはHandlerMethodReturnValueHandlerを実装しており
実際にはaddHandlersで追加されたHandlerに処理を移譲するようなクラスになっている。
HandlerMethodReturnValueHandlerCompositeのgetReturnValueHandlerにてaddHandlersで追加されたHandlerのsupportsReturnTypeの戻り値を見て
実際に使うMethodHandlerの決定が行われる。
このメソッドは、
AbstractMethodMessageHandler
→AbstractMethodMessageHandler
→AbstractMethodMessageHandler
→HandlerMethodReturnValueHandlerComposite#handleReturnValue
→HandlerMethodReturnValueHandlerComposite#getReturnValueHandler
の流れで呼ばれる。
Websocket Scopeの実装
Spring MessagingとSpring Websocketの連携では、websocket scopedなBeanの定義が可能になっている。 これらのScopeの実装に関わるクラスは以下のクラスである。
- org.springframework.messaging.simp.SimpSessionScope
- org.springframework.messaging.simp.SimpAttributesContextHolder
- org.springframework.messaging.simp.SimpAttributes
org.springframework.messaging.simp.SimpAttributesContextHolderの内部にて
ThreadLocalな値を保持しており、その値の型はSimpAttributes型になっている。
SimpAttributesはただのMap
解説はここでは特にしない。
また、SimpAnnotationMethodMessageHandlerのhandleMatchにてSimpAttributesContextHolderのsetAttributesFromMessageとresetAttributesが呼び出されており
ここでWebsocket Scopeの実装が行われているように伺える。
まとめ
とりあえずこれまでのSpringはここまで。