|
21 | 21 | import java.util.List;
|
22 | 22 | import java.util.Map;
|
23 | 23 |
|
| 24 | +import org.springframework.beans.factory.FactoryBean; |
| 25 | +import org.springframework.web.socket.WebSocketHandler; |
| 26 | +import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory; |
24 | 27 | import org.w3c.dom.Element;
|
25 | 28 |
|
26 | 29 | import org.springframework.beans.MutablePropertyValues;
|
|
89 | 92 | */
|
90 | 93 | class MessageBrokerBeanDefinitionParser implements BeanDefinitionParser {
|
91 | 94 |
|
92 |
| - private static final String SOCKJS_SCHEDULER_BEAN_NAME = "messageBrokerSockJsScheduler"; |
| 95 | + public static final String WEB_SOCKET_HANDLER_BEAN_NAME = "subProtocolWebSocketHandler"; |
| 96 | + |
| 97 | + public static final String SOCKJS_SCHEDULER_BEAN_NAME = "messageBrokerSockJsScheduler"; |
93 | 98 |
|
94 | 99 | private static final int DEFAULT_MAPPING_ORDER = 1;
|
95 | 100 |
|
@@ -156,7 +161,7 @@ public BeanDefinition parse(Element element, ParserContext context) {
|
156 | 161 | scopeConfigurer.getPropertyValues().add("scopes", scopeMap);
|
157 | 162 | registerBeanDefByName("webSocketScopeConfigurer", scopeConfigurer, context, source);
|
158 | 163 |
|
159 |
| - registerWebSocketMessageBrokerStats(subProtoHandler, broker, inChannel, outChannel, context, source); |
| 164 | + registerWebSocketMessageBrokerStats(broker, inChannel, outChannel, context, source); |
160 | 165 |
|
161 | 166 | context.popAndRegisterContainingComponent();
|
162 | 167 | return null;
|
@@ -228,22 +233,32 @@ private RuntimeBeanReference registerSubProtoHandler(Element element, RuntimeBea
|
228 | 233 | cavs.addIndexedArgumentValue(0, inChannel);
|
229 | 234 | cavs.addIndexedArgumentValue(1, outChannel);
|
230 | 235 |
|
231 |
| - RootBeanDefinition beanDef = new RootBeanDefinition(SubProtocolWebSocketHandler.class, cavs, null); |
232 |
| - beanDef.getPropertyValues().addPropertyValue("protocolHandlers", stompHandlerDef); |
| 236 | + RootBeanDefinition handlerDef = new RootBeanDefinition(SubProtocolWebSocketHandler.class, cavs, null); |
| 237 | + handlerDef.getPropertyValues().addPropertyValue("protocolHandlers", stompHandlerDef); |
| 238 | + registerBeanDefByName(WEB_SOCKET_HANDLER_BEAN_NAME, handlerDef, context, source); |
| 239 | + RuntimeBeanReference result = new RuntimeBeanReference(WEB_SOCKET_HANDLER_BEAN_NAME); |
233 | 240 |
|
234 | 241 | Element transportElem = DomUtils.getChildElementByTagName(element, "transport");
|
235 | 242 | if (transportElem != null) {
|
236 | 243 | if (transportElem.hasAttribute("message-size")) {
|
237 | 244 | stompHandlerDef.getPropertyValues().add("messageSizeLimit", transportElem.getAttribute("message-size"));
|
238 | 245 | }
|
239 | 246 | if (transportElem.hasAttribute("send-timeout")) {
|
240 |
| - beanDef.getPropertyValues().add("sendTimeLimit", transportElem.getAttribute("send-timeout")); |
| 247 | + handlerDef.getPropertyValues().add("sendTimeLimit", transportElem.getAttribute("send-timeout")); |
241 | 248 | }
|
242 | 249 | if (transportElem.hasAttribute("send-buffer-size")) {
|
243 |
| - beanDef.getPropertyValues().add("sendBufferSizeLimit", transportElem.getAttribute("send-buffer-size")); |
| 250 | + handlerDef.getPropertyValues().add("sendBufferSizeLimit", transportElem.getAttribute("send-buffer-size")); |
| 251 | + } |
| 252 | + Element factoriesElement = DomUtils.getChildElementByTagName(transportElem, "decorator-factories"); |
| 253 | + if (factoriesElement != null) { |
| 254 | + ManagedList<Object> factories = extractBeanSubElements(factoriesElement, context); |
| 255 | + RootBeanDefinition factoryBean = new RootBeanDefinition(DecoratingFactoryBean.class); |
| 256 | + factoryBean.getConstructorArgumentValues().addIndexedArgumentValue(0, handlerDef); |
| 257 | + factoryBean.getConstructorArgumentValues().addIndexedArgumentValue(1, factories); |
| 258 | + result = new RuntimeBeanReference(registerBeanDef(factoryBean, context, source)); |
244 | 259 | }
|
245 | 260 | }
|
246 |
| - return new RuntimeBeanReference(registerBeanDef(beanDef, context, source)); |
| 261 | + return result; |
247 | 262 | }
|
248 | 263 |
|
249 | 264 | private RuntimeBeanReference registerRequestHandler(Element element, RuntimeBeanReference subProtoHandler,
|
@@ -448,14 +463,15 @@ private RuntimeBeanReference registerUserDestinationMessageHandler(RuntimeBeanRe
|
448 | 463 | return new RuntimeBeanReference(registerBeanDef(beanDef, context, source));
|
449 | 464 | }
|
450 | 465 |
|
451 |
| - private void registerWebSocketMessageBrokerStats(RuntimeBeanReference subProtoHandler, |
452 |
| - RootBeanDefinition broker, RuntimeBeanReference inChannel, RuntimeBeanReference outChannel, |
453 |
| - ParserContext context, Object source) { |
| 466 | + private void registerWebSocketMessageBrokerStats(RootBeanDefinition broker, RuntimeBeanReference inChannel, |
| 467 | + RuntimeBeanReference outChannel, ParserContext context, Object source) { |
454 | 468 |
|
455 | 469 | RootBeanDefinition beanDef = new RootBeanDefinition(WebSocketMessageBrokerStats.class);
|
456 |
| - beanDef.getPropertyValues().add("subProtocolWebSocketHandler", subProtoHandler); |
457 | 470 |
|
458 |
| - if (StompBrokerRelayMessageHandler.class.equals(broker.getBeanClass())) { |
| 471 | + RuntimeBeanReference webSocketHandler = new RuntimeBeanReference(WEB_SOCKET_HANDLER_BEAN_NAME); |
| 472 | + beanDef.getPropertyValues().add("subProtocolWebSocketHandler", webSocketHandler); |
| 473 | + |
| 474 | + if (StompBrokerRelayMessageHandler.class.equals(broker.getBeanClass())) { |
459 | 475 | beanDef.getPropertyValues().add("stompBrokerRelay", broker);
|
460 | 476 | }
|
461 | 477 | String name = inChannel.getBeanName() + "Executor";
|
@@ -486,4 +502,37 @@ private static void registerBeanDefByName(String name, RootBeanDefinition beanDe
|
486 | 502 | context.registerComponent(new BeanComponentDefinition(beanDef, name));
|
487 | 503 | }
|
488 | 504 |
|
| 505 | + |
| 506 | + private static class DecoratingFactoryBean implements FactoryBean<WebSocketHandler> { |
| 507 | + |
| 508 | + private final WebSocketHandler handler; |
| 509 | + |
| 510 | + private final List<WebSocketHandlerDecoratorFactory> factories; |
| 511 | + |
| 512 | + |
| 513 | + private DecoratingFactoryBean(WebSocketHandler handler, List<WebSocketHandlerDecoratorFactory> factories) { |
| 514 | + this.handler = handler; |
| 515 | + this.factories = factories; |
| 516 | + } |
| 517 | + |
| 518 | + @Override |
| 519 | + public WebSocketHandler getObject() throws Exception { |
| 520 | + WebSocketHandler result = this.handler; |
| 521 | + for (WebSocketHandlerDecoratorFactory factory : this.factories) { |
| 522 | + result = factory.decorate(result); |
| 523 | + } |
| 524 | + return result; |
| 525 | + } |
| 526 | + |
| 527 | + @Override |
| 528 | + public Class<?> getObjectType() { |
| 529 | + return WebSocketHandler.class; |
| 530 | + } |
| 531 | + |
| 532 | + @Override |
| 533 | + public boolean isSingleton() { |
| 534 | + return true; |
| 535 | + } |
| 536 | + } |
| 537 | + |
489 | 538 | }
|
0 commit comments