From 9c7b4ff9bac7986f9c94d4c881aab3124a7d186d Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Wed, 26 Aug 2020 08:21:30 +0100 Subject: [PATCH] Public method to register RSocket handler methods Closes gh-25639 --- .../AbstractMethodMessageHandler.java | 20 +++++++++---------- .../reactive/MethodMessageHandlerTests.java | 12 +++++------ 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java index c193249c60..1d85930585 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java @@ -22,10 +22,11 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -50,7 +51,6 @@ import org.springframework.messaging.handler.invocation.AbstractExceptionHandler import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; -import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.ObjectUtils; import org.springframework.util.RouteMatcher; @@ -104,9 +104,9 @@ public abstract class AbstractMethodMessageHandler @Nullable private String beanName; - private final Map handlerMethods = new LinkedHashMap<>(64); + private final Map handlerMethods = new ConcurrentHashMap<>(64); - private final MultiValueMap destinationLookup = new LinkedMultiValueMap<>(48); + private final Map> destinationLookup = new ConcurrentHashMap<>(48); /** @@ -229,7 +229,7 @@ public abstract class AbstractMethodMessageHandler * (e.g. for non-pattern destinations). */ public MultiValueMap getDestinationLookup() { - return CollectionUtils.unmodifiableMultiValueMap(this.destinationLookup); + return CollectionUtils.unmodifiableMultiValueMap(CollectionUtils.toMultiValueMap(this.destinationLookup)); } /** @@ -366,16 +366,15 @@ public abstract class AbstractMethodMessageHandler /** * Register a handler method and its unique mapping. - *

Note: This method is protected and can be invoked by - * subclasses. Keep in mind however that the registration is not protected - * for concurrent use, and is expected to be done on startup. + *

Note: As of 5.3 this method is public (rather than + * protected) and can be used both at startup and at runtime. * @param handler the bean name of the handler or the handler instance * @param method the method to register * @param mapping the mapping conditions associated with the handler method * @throws IllegalStateException if another method was already registered * under the same mapping */ - protected final void registerHandlerMethod(Object handler, Method method, T mapping) { + public final void registerHandlerMethod(Object handler, Method method, T mapping) { Assert.notNull(mapping, "Mapping must not be null"); HandlerMethod newHandlerMethod = createHandlerMethod(handler, method); HandlerMethod oldHandlerMethod = this.handlerMethods.get(mapping); @@ -390,7 +389,8 @@ public abstract class AbstractMethodMessageHandler this.handlerMethods.put(mapping, newHandlerMethod); for (String pattern : getDirectLookupMappings(mapping)) { - this.destinationLookup.add(pattern, mapping); + List values = this.destinationLookup.computeIfAbsent(pattern, p -> new CopyOnWriteArrayList<>()); + values.add(mapping); } } diff --git a/spring-messaging/src/test/java/org/springframework/messaging/handler/invocation/reactive/MethodMessageHandlerTests.java b/spring-messaging/src/test/java/org/springframework/messaging/handler/invocation/reactive/MethodMessageHandlerTests.java index be505f7ffe..d651e7d35b 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/handler/invocation/reactive/MethodMessageHandlerTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/handler/invocation/reactive/MethodMessageHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -77,8 +77,10 @@ public class MethodMessageHandlerTests { public void bestMatch() throws NoSuchMethodException { TestMethodMessageHandler handler = new TestMethodMessageHandler(); TestController controller = new TestController(); - handler.register(controller, TestController.class.getMethod("handleMessageMatch1"), "/bestmatch/{foo}/path"); - handler.register(controller, TestController.class.getMethod("handleMessageMatch2"), "/bestmatch/*/*"); + handler.registerHandlerMethod(controller, + TestController.class.getMethod("handleMessageMatch1"), "/bestmatch/{foo}/path"); + handler.registerHandlerMethod(controller, + TestController.class.getMethod("handleMessageMatch2"), "/bestmatch/*/*"); handler.afterPropertiesSet(); Message message = new GenericMessage<>("body", Collections.singletonMap( @@ -221,10 +223,6 @@ public class MethodMessageHandlerTests { return this.returnValueHandler.getLastReturnValue(); } - public void register(Object handler, Method method, String mapping) { - super.registerHandlerMethod(handler, method, mapping); - } - @Override protected String getMappingForMethod(Method method, Class handlerType) { String methodName = method.getName();