30
30
import org .springframework .context .ApplicationContext ;
31
31
import org .springframework .context .ConfigurableApplicationContext ;
32
32
import org .springframework .context .EmbeddedValueResolverAware ;
33
- import org .springframework .context .SmartLifecycle ;
34
33
import org .springframework .core .annotation .AnnotatedElementUtils ;
35
34
import org .springframework .core .codec .Decoder ;
36
35
import org .springframework .core .convert .ConversionService ;
37
36
import org .springframework .format .support .DefaultFormattingConversionService ;
38
37
import org .springframework .lang .Nullable ;
39
38
import org .springframework .messaging .Message ;
40
- import org .springframework .messaging .ReactiveSubscribableChannel ;
41
39
import org .springframework .messaging .handler .CompositeMessageCondition ;
42
40
import org .springframework .messaging .handler .DestinationPatternsMessageCondition ;
43
41
import org .springframework .messaging .handler .annotation .MessageMapping ;
74
72
* @see AbstractEncoderMethodReturnValueHandler
75
73
*/
76
74
public class MessageMappingMessageHandler extends AbstractMethodMessageHandler <CompositeMessageCondition >
77
- implements SmartLifecycle , EmbeddedValueResolverAware {
75
+ implements EmbeddedValueResolverAware {
78
76
79
- private final ReactiveSubscribableChannel inboundChannel ;
77
+ @ Nullable
78
+ private Predicate <Class <?>> handlerPredicate =
79
+ beanType -> AnnotatedElementUtils .hasAnnotation (beanType , Controller .class );
80
80
81
81
private final List <Decoder <?>> decoders = new ArrayList <>();
82
82
@@ -90,20 +90,63 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
90
90
@ Nullable
91
91
private StringValueResolver valueResolver ;
92
92
93
- private volatile boolean running = false ;
94
-
95
- private final Object lifecycleMonitor = new Object ();
96
-
97
93
98
- public MessageMappingMessageHandler (ReactiveSubscribableChannel inboundChannel ) {
99
- Assert .notNull (inboundChannel , "`inboundChannel` is required" );
100
- this .inboundChannel = inboundChannel ;
94
+ public MessageMappingMessageHandler () {
101
95
this .pathMatcher = new AntPathMatcher ();
102
96
((AntPathMatcher ) this .pathMatcher ).setPathSeparator ("." );
103
- setHandlerPredicate (beanType -> AnnotatedElementUtils .hasAnnotation (beanType , Controller .class ));
104
97
}
105
98
106
99
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
+
107
150
/**
108
151
* Configure the decoders to use for incoming payloads.
109
152
*/
@@ -203,34 +246,9 @@ protected List<? extends HandlerMethodReturnValueHandler> initReturnValueHandler
203
246
return Collections .emptyList ();
204
247
}
205
248
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
-
231
249
@ Override
232
- public final boolean isRunning () {
233
- return this .running ;
250
+ protected Predicate < Class <?>> initHandlerPredicate () {
251
+ return this .handlerPredicate ;
234
252
}
235
253
236
254
0 commit comments