diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java index bb8a236999..88d24a6b7d 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java @@ -83,10 +83,6 @@ import org.springframework.validation.Validator; public class MessageMappingMessageHandler extends AbstractMethodMessageHandler implements EmbeddedValueResolverAware { - @Nullable - private Predicate> handlerPredicate = - beanType -> AnnotatedElementUtils.hasAnnotation(beanType, Controller.class); - private final List> decoders = new ArrayList<>(); @Nullable @@ -104,59 +100,10 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler AnnotatedElementUtils.hasAnnotation(type, Controller.class)); } - /** - * Manually configure handlers to check for {@code @MessageMapping} methods. - *

Note: the given handlers are not required to be - * annotated with {@code @Controller}. Consider also using - * {@link #setAutoDetectDisabled()} if the intent is to use these handlers - * instead of, and not in addition to {@code @Controller} classes. Or - * alternatively use {@link #setHandlerPredicate(Predicate)} to select a - * different set of beans based on a different criteria. - * @param handlers the handlers to register - * @see #setAutoDetectDisabled() - * @see #setHandlerPredicate(Predicate) - */ - public void setHandlers(List handlers) { - for (Object handler : handlers) { - detectHandlerMethods(handler); - } - // Disable auto-detection.. - this.handlerPredicate = null; - } - - /** - * Configure the predicate to use for selecting which Spring beans to check - * for {@code @MessageMapping} methods. When set to {@code null}, - * auto-detection is turned off which is what - * {@link #setAutoDetectDisabled()} does internally. - *

The predicate used by default selects {@code @Controller} classes. - * @see #setHandlers(List) - * @see #setAutoDetectDisabled() - */ - public void setHandlerPredicate(@Nullable Predicate> handlerPredicate) { - this.handlerPredicate = handlerPredicate; - } - - /** - * Return the {@link #setHandlerPredicate configured} handler predicate. - */ - @Nullable - public Predicate> getHandlerPredicate() { - return this.handlerPredicate; - } - - /** - * Disable auto-detection of {@code @MessageMapping} methods, e.g. in - * {@code @Controller}s, by setting {@link #setHandlerPredicate(Predicate) - * setHandlerPredicate(null)}. - */ - public void setAutoDetectDisabled() { - this.handlerPredicate = null; - } - /** * Configure the decoders to use for incoming payloads. */ @@ -264,11 +211,6 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler> initHandlerPredicate() { - return this.handlerPredicate; - } - @Override protected CompositeMessageCondition getMappingForMethod(Method method, Class handlerType) { 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 43da16b095..5fb60c9074 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 @@ -86,6 +86,12 @@ public abstract class AbstractMethodMessageHandler protected final Log logger = LogFactory.getLog(getClass()); + @Nullable + private Predicate> handlerPredicate; + + @Nullable + List handlers; + private ArgumentResolverConfigurer argumentResolverConfigurer = new ArgumentResolverConfigurer(); private ReturnValueHandlerConfigurer returnValueHandlerConfigurer = new ReturnValueHandlerConfigurer(); @@ -103,6 +109,38 @@ public abstract class AbstractMethodMessageHandler private final MultiValueMap destinationLookup = new LinkedMultiValueMap<>(64); + /** + * Configure a predicate for selecting which Spring beans to check for the + * presence of message handler methods. + *

This is not set by default. However sub-classes may initialize it to + * some default strategy (e.g. {@code @Controller} classes). + * @see #setHandlers(List) + */ + public void setHandlerPredicate(@Nullable Predicate> handlerPredicate) { + this.handlerPredicate = handlerPredicate; + } + + /** + * Return the {@link #setHandlerPredicate configured} handler predicate. + */ + @Nullable + public Predicate> getHandlerPredicate() { + return this.handlerPredicate; + } + + /** + * Manually configure the handlers to check for the presence of message + * handling methods, which also disables auto-detection via a + * {@link #setHandlerPredicate(Predicate) handlerPredicate}. If you do not + * want to disable auto-detection, then call this method first, and then set + * the handler predicate. + * @param handlers the handlers to check + */ + public void setHandlers(List handlers) { + this.handlers = handlers; + this.handlerPredicate = null; + } + /** * Configure custom resolvers for handler method arguments. */ @@ -233,9 +271,14 @@ public abstract class AbstractMethodMessageHandler logger.warn("No ApplicationContext available for detecting beans with message handling methods."); return; } - Predicate> handlerPredicate = initHandlerPredicate(); - if (handlerPredicate == null) { - logger.warn("[" + getBeanName() + "] No auto-detection of handler methods (e.g. in @Controller)."); + if (this.handlers != null) { + for (Object handler : this.handlers) { + detectHandlerMethods(handler); + } + } + Predicate> predicate = this.handlerPredicate; + if (predicate == null) { + logger.warn("[" + getBeanName() + "] Auto-detection of message handling methods is off."); return; } for (String beanName : this.applicationContext.getBeanNamesForType(Object.class)) { @@ -250,21 +293,13 @@ public abstract class AbstractMethodMessageHandler logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex); } } - if (beanType != null && handlerPredicate.test(beanType)) { + if (beanType != null && predicate.test(beanType)) { detectHandlerMethods(beanName); } } } } - /** - * Return the predicate to use to check whether a given Spring bean should - * be introspected for message handling methods. If {@code null} is - * returned, auto-detection is effectively disabled. - */ - @Nullable - protected abstract Predicate> initHandlerPredicate(); - /** * Detect if the given handler has any methods that can handle messages and if * so register it with the extracted mapping information. 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 5adc945f2f..229ef2227b 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 @@ -24,7 +24,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; -import java.util.function.Predicate; import org.junit.Test; import org.reactivestreams.Publisher; @@ -203,6 +202,10 @@ public class MethodMessageHandlerTests { private PathMatcher pathMatcher = new AntPathMatcher(); + public TestMethodMessageHandler() { + setHandlerPredicate(handlerType -> handlerType.getName().endsWith("Controller")); + } + @Override protected List initArgumentResolvers() { return Collections.emptyList(); @@ -213,11 +216,6 @@ public class MethodMessageHandlerTests { return Collections.singletonList(this.returnValueHandler); } - @Override - protected Predicate> initHandlerPredicate() { - return handlerType -> handlerType.getName().endsWith("Controller"); - } - @Nullable public Object getLastReturnValue() { return this.returnValueHandler.getLastReturnValue();