Skip to content

Commit fa95b01

Browse files
committed
Direct delegation to RSocketMessageHandler
Simplify handling by eliminating the use of a message channel. Instead MessageHandlerAcceptor now extends from RSocketMessageHandler and delegates directly to it. See gh-21987
1 parent 555dca9 commit fa95b01

File tree

13 files changed

+223
-467
lines changed

13 files changed

+223
-467
lines changed

spring-messaging/src/main/java/org/springframework/messaging/ReactiveMessageChannel.java

-38
This file was deleted.

spring-messaging/src/main/java/org/springframework/messaging/ReactiveSubscribableChannel.java

-42
This file was deleted.

spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/reactive/MessageMappingMessageHandler.java

+57-39
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,12 @@
3030
import org.springframework.context.ApplicationContext;
3131
import org.springframework.context.ConfigurableApplicationContext;
3232
import org.springframework.context.EmbeddedValueResolverAware;
33-
import org.springframework.context.SmartLifecycle;
3433
import org.springframework.core.annotation.AnnotatedElementUtils;
3534
import org.springframework.core.codec.Decoder;
3635
import org.springframework.core.convert.ConversionService;
3736
import org.springframework.format.support.DefaultFormattingConversionService;
3837
import org.springframework.lang.Nullable;
3938
import org.springframework.messaging.Message;
40-
import org.springframework.messaging.ReactiveSubscribableChannel;
4139
import org.springframework.messaging.handler.CompositeMessageCondition;
4240
import org.springframework.messaging.handler.DestinationPatternsMessageCondition;
4341
import org.springframework.messaging.handler.annotation.MessageMapping;
@@ -74,9 +72,11 @@
7472
* @see AbstractEncoderMethodReturnValueHandler
7573
*/
7674
public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<CompositeMessageCondition>
77-
implements SmartLifecycle, EmbeddedValueResolverAware {
75+
implements EmbeddedValueResolverAware {
7876

79-
private final ReactiveSubscribableChannel inboundChannel;
77+
@Nullable
78+
private Predicate<Class<?>> handlerPredicate =
79+
beanType -> AnnotatedElementUtils.hasAnnotation(beanType, Controller.class);
8080

8181
private final List<Decoder<?>> decoders = new ArrayList<>();
8282

@@ -90,20 +90,63 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
9090
@Nullable
9191
private StringValueResolver valueResolver;
9292

93-
private volatile boolean running = false;
94-
95-
private final Object lifecycleMonitor = new Object();
96-
9793

98-
public MessageMappingMessageHandler(ReactiveSubscribableChannel inboundChannel) {
99-
Assert.notNull(inboundChannel, "`inboundChannel` is required");
100-
this.inboundChannel = inboundChannel;
94+
public MessageMappingMessageHandler() {
10195
this.pathMatcher = new AntPathMatcher();
10296
((AntPathMatcher) this.pathMatcher).setPathSeparator(".");
103-
setHandlerPredicate(beanType -> AnnotatedElementUtils.hasAnnotation(beanType, Controller.class));
10497
}
10598

10699

100+
/**
101+
* Manually configure handlers to check for {@code @MessageMapping} methods.
102+
* <p><strong>Note:</strong> the given handlers are not required to be
103+
* annotated with {@code @Controller}. Consider also using
104+
* {@link #setAutoDetectDisabled()} if the intent is to use these handlers
105+
* instead of, and not in addition to {@code @Controller} classes. Or
106+
* alternatively use {@link #setHandlerPredicate(Predicate)} to select a
107+
* different set of beans based on a different criteria.
108+
* @param handlers the handlers to register
109+
* @see #setAutoDetectDisabled()
110+
* @see #setHandlerPredicate(Predicate)
111+
*/
112+
public void setHandlers(List<Object> handlers) {
113+
for (Object handler : handlers) {
114+
detectHandlerMethods(handler);
115+
}
116+
// Disable auto-detection..
117+
this.handlerPredicate = null;
118+
}
119+
120+
/**
121+
* Configure the predicate to use for selecting which Spring beans to check
122+
* for {@code @MessageMapping} methods. When set to {@code null},
123+
* auto-detection is turned off which is what
124+
* {@link #setAutoDetectDisabled()} does internally.
125+
* <p>The predicate used by default selects {@code @Controller} classes.
126+
* @see #setHandlers(List)
127+
* @see #setAutoDetectDisabled()
128+
*/
129+
public void setHandlerPredicate(@Nullable Predicate<Class<?>> handlerPredicate) {
130+
this.handlerPredicate = handlerPredicate;
131+
}
132+
133+
/**
134+
* Return the {@link #setHandlerPredicate configured} handler predicate.
135+
*/
136+
@Nullable
137+
public Predicate<Class<?>> getHandlerPredicate() {
138+
return this.handlerPredicate;
139+
}
140+
141+
/**
142+
* Disable auto-detection of {@code @MessageMapping} methods, e.g. in
143+
* {@code @Controller}s, by setting {@link #setHandlerPredicate(Predicate)
144+
* setHandlerPredicate(null)}.
145+
*/
146+
public void setAutoDetectDisabled() {
147+
this.handlerPredicate = null;
148+
}
149+
107150
/**
108151
* Configure the decoders to use for incoming payloads.
109152
*/
@@ -203,34 +246,9 @@ protected List<? extends HandlerMethodReturnValueHandler> initReturnValueHandler
203246
return Collections.emptyList();
204247
}
205248

206-
207-
@Override
208-
public final void start() {
209-
synchronized (this.lifecycleMonitor) {
210-
this.inboundChannel.subscribe(this);
211-
this.running = true;
212-
}
213-
}
214-
215-
@Override
216-
public final void stop() {
217-
synchronized (this.lifecycleMonitor) {
218-
this.running = false;
219-
this.inboundChannel.unsubscribe(this);
220-
}
221-
}
222-
223-
@Override
224-
public final void stop(Runnable callback) {
225-
synchronized (this.lifecycleMonitor) {
226-
stop();
227-
callback.run();
228-
}
229-
}
230-
231249
@Override
232-
public final boolean isRunning() {
233-
return this.running;
250+
protected Predicate<Class<?>> initHandlerPredicate() {
251+
return this.handlerPredicate;
234252
}
235253

236254

spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java

+28-25
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.commons.logging.LogFactory;
3131
import reactor.core.publisher.Mono;
3232

33+
import org.springframework.beans.factory.BeanNameAware;
3334
import org.springframework.beans.factory.InitializingBean;
3435
import org.springframework.context.ApplicationContext;
3536
import org.springframework.context.ApplicationContextAware;
@@ -47,6 +48,7 @@
4748
import org.springframework.util.CollectionUtils;
4849
import org.springframework.util.LinkedMultiValueMap;
4950
import org.springframework.util.MultiValueMap;
51+
import org.springframework.util.ObjectUtils;
5052

5153
/**
5254
* Abstract base class for reactive HandlerMethod-based message handling.
@@ -61,7 +63,7 @@
6163
* @param <T> the type of the Object that contains information mapping information
6264
*/
6365
public abstract class AbstractMethodMessageHandler<T>
64-
implements ReactiveMessageHandler, ApplicationContextAware, InitializingBean {
66+
implements ReactiveMessageHandler, ApplicationContextAware, InitializingBean, BeanNameAware {
6567

6668
/**
6769
* Bean name prefix for target beans behind scoped proxies. Used to exclude those
@@ -79,9 +81,6 @@ public abstract class AbstractMethodMessageHandler<T>
7981
protected final Log logger = LogFactory.getLog(getClass());
8082

8183

82-
@Nullable
83-
private Predicate<Class<?>> handlerPredicate;
84-
8584
private ArgumentResolverConfigurer argumentResolverConfigurer = new ArgumentResolverConfigurer();
8685

8786
private ReturnValueHandlerConfigurer returnValueHandlerConfigurer = new ReturnValueHandlerConfigurer();
@@ -91,29 +90,14 @@ public abstract class AbstractMethodMessageHandler<T>
9190
@Nullable
9291
private ApplicationContext applicationContext;
9392

93+
@Nullable
94+
private String beanName;
95+
9496
private final Map<T, HandlerMethod> handlerMethods = new LinkedHashMap<>(64);
9597

9698
private final MultiValueMap<String, T> destinationLookup = new LinkedMultiValueMap<>(64);
9799

98100

99-
/**
100-
* Configure a predicate to decide if which beans in the Spring context
101-
* should be checked to see if they have message handling methods.
102-
* <p>By default this is not set and sub-classes should configure it in
103-
* order to enable auto-detection of message handling methods.
104-
*/
105-
public void setHandlerPredicate(@Nullable Predicate<Class<?>> handlerPredicate) {
106-
this.handlerPredicate = handlerPredicate;
107-
}
108-
109-
/**
110-
* Return the {@link #setHandlerPredicate configured} handler predicate.
111-
*/
112-
@Nullable
113-
public Predicate<Class<?>> getHandlerPredicate() {
114-
return this.handlerPredicate;
115-
}
116-
117101
/**
118102
* Configure custom resolvers for handler method arguments.
119103
*/
@@ -170,6 +154,16 @@ public ApplicationContext getApplicationContext() {
170154
return this.applicationContext;
171155
}
172156

157+
@Override
158+
public void setBeanName(String name) {
159+
this.beanName = name;
160+
}
161+
162+
public String getBeanName() {
163+
return this.beanName != null ? this.beanName :
164+
getClass().getSimpleName() + "@" + ObjectUtils.getIdentityHexString(this);
165+
}
166+
173167
/**
174168
* Subclasses can invoke this method to populate the MessagingAdviceBean cache
175169
* (e.g. to support "global" {@code @MessageExceptionHandler}).
@@ -234,8 +228,9 @@ private void initHandlerMethods() {
234228
logger.warn("No ApplicationContext available for detecting beans with message handling methods.");
235229
return;
236230
}
237-
if (this.handlerPredicate == null) {
238-
logger.warn("'handlerPredicate' not configured: no auto-detection of message handling methods.");
231+
Predicate<Class<?>> handlerPredicate = initHandlerPredicate();
232+
if (handlerPredicate == null) {
233+
logger.warn("[" + getBeanName() + "] No auto-detection of handler methods (e.g. in @Controller).");
239234
return;
240235
}
241236
for (String beanName : this.applicationContext.getBeanNamesForType(Object.class)) {
@@ -250,13 +245,21 @@ private void initHandlerMethods() {
250245
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
251246
}
252247
}
253-
if (beanType != null && this.handlerPredicate.test(beanType)) {
248+
if (beanType != null && handlerPredicate.test(beanType)) {
254249
detectHandlerMethods(beanName);
255250
}
256251
}
257252
}
258253
}
259254

255+
/**
256+
* Return the predicate to use to check whether a given Spring bean should
257+
* be introspected for message handling methods. If {@code null} is
258+
* returned, auto-detection is effectively disabled.
259+
*/
260+
@Nullable
261+
protected abstract Predicate<Class<?>> initHandlerPredicate();
262+
260263
/**
261264
* Detect if the given handler has any methods that can handle messages and if
262265
* so register it with the extracted mapping information.

0 commit comments

Comments
 (0)