@@ -183,7 +183,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
183
183
184
184
private final Map <Class <?>, HandlerMethod > handlerMessageMethods ;
185
185
186
- private final List <Map <Class <?>, HandlerMethod >> handlerMethodsList ;
186
+ private final List <Map <Class <?>, HandlerMethod >> handlerMethodsList = new LinkedList <>() ;
187
187
188
188
private HandlerMethod handlerMethod ;
189
189
@@ -258,10 +258,11 @@ private MessagingMethodInvokerHelper(Object targetObject, Class<? extends Annota
258
258
259
259
Assert .notNull (targetObject , "targetObject must not be null" );
260
260
this .targetObject = targetObject ;
261
- createHandlerMethod ();
261
+ this . handlerMethod = createHandlerMethod (this . method );
262
262
this .handlerMethods = null ;
263
263
this .handlerMessageMethods = null ;
264
- this .handlerMethodsList = null ;
264
+ this .handlerMethodsList .add (
265
+ Collections .singletonMap (this .handlerMethod .targetParameterType , this .handlerMethod ));
265
266
setDisplayString (targetObject , method );
266
267
267
268
JsonObjectMapper <?, ?> mapper ;
@@ -274,6 +275,54 @@ private MessagingMethodInvokerHelper(Object targetObject, Class<? extends Annota
274
275
this .jsonObjectMapper = mapper ;
275
276
}
276
277
278
+ private MessagingMethodInvokerHelper (Object targetObject , Class <? extends Annotation > annotationType ,
279
+ String methodName , Class <?> expectedType , boolean canProcessMessageList ) {
280
+
281
+ this .annotationType = annotationType ;
282
+ this .methodName = methodName ;
283
+ this .canProcessMessageList = canProcessMessageList ;
284
+ Assert .notNull (targetObject , "targetObject must not be null" );
285
+ if (expectedType != null ) {
286
+ this .expectedType = TypeDescriptor .valueOf (expectedType );
287
+ }
288
+ else {
289
+ this .expectedType = null ;
290
+ }
291
+ this .targetObject = targetObject ;
292
+ Map <String , Map <Class <?>, HandlerMethod >> handlerMethodsForTarget =
293
+ findHandlerMethodsForTarget (annotationType , methodName , expectedType != null );
294
+ Map <Class <?>, HandlerMethod > methods = handlerMethodsForTarget .get (CANDIDATE_METHODS );
295
+ Map <Class <?>, HandlerMethod > messageMethods = handlerMethodsForTarget .get (CANDIDATE_MESSAGE_METHODS );
296
+ if ((methods .size () == 1 && messageMethods .isEmpty ()) ||
297
+ (messageMethods .size () == 1 && methods .isEmpty ())) {
298
+ if (methods .size () == 1 ) {
299
+ this .handlerMethod = methods .values ().iterator ().next ();
300
+ }
301
+ else {
302
+ this .handlerMethod = messageMethods .values ().iterator ().next ();
303
+ }
304
+ }
305
+ else {
306
+ this .handlerMethod = null ;
307
+ }
308
+
309
+ this .handlerMethods = methods ;
310
+ this .handlerMessageMethods = messageMethods ;
311
+ //TODO Consider to use global option to determine a precedence of methods
312
+ this .handlerMethodsList .add (this .handlerMethods );
313
+ this .handlerMethodsList .add (this .handlerMessageMethods );
314
+
315
+ setDisplayString (targetObject , methodName );
316
+ JsonObjectMapper <?, ?> mapper ;
317
+ try {
318
+ mapper = JsonObjectMapperProvider .newInstance ();
319
+ }
320
+ catch (IllegalStateException e ) {
321
+ mapper = null ;
322
+ }
323
+ this .jsonObjectMapper = mapper ;
324
+ }
325
+
277
326
/**
278
327
* A {@code boolean} flag to use SpEL Expression evaluation or {@link InvocableHandlerMethod}
279
328
* for target method invocation.
@@ -346,76 +395,28 @@ public boolean isRunning() {
346
395
* Private constructors for internal use
347
396
*/
348
397
349
- private MessagingMethodInvokerHelper (Object targetObject , Class <? extends Annotation > annotationType ,
350
- String methodName , Class <?> expectedType , boolean canProcessMessageList ) {
351
-
352
- this .annotationType = annotationType ;
353
- this .methodName = methodName ;
354
- this .canProcessMessageList = canProcessMessageList ;
355
- Assert .notNull (targetObject , "targetObject must not be null" );
356
- if (expectedType != null ) {
357
- this .expectedType = TypeDescriptor .valueOf (expectedType );
358
- }
359
- else {
360
- this .expectedType = null ;
361
- }
362
- this .targetObject = targetObject ;
363
- Map <String , Map <Class <?>, HandlerMethod >> handlerMethodsForTarget =
364
- findHandlerMethodsForTarget (targetObject , annotationType , methodName , expectedType != null );
365
- Map <Class <?>, HandlerMethod > methods = handlerMethodsForTarget .get (CANDIDATE_METHODS );
366
- Map <Class <?>, HandlerMethod > messageMethods = handlerMethodsForTarget .get (CANDIDATE_MESSAGE_METHODS );
367
- if ((methods .size () == 1 && messageMethods .isEmpty ()) ||
368
- (messageMethods .size () == 1 && methods .isEmpty ())) {
369
- if (methods .size () == 1 ) {
370
- this .handlerMethod = methods .values ().iterator ().next ();
371
- }
372
- else {
373
- this .handlerMethod = messageMethods .values ().iterator ().next ();
374
- }
375
- this .handlerMethods = null ;
376
- this .handlerMessageMethods = null ;
377
- this .handlerMethodsList = null ;
378
- }
379
- else {
380
- this .handlerMethod = null ;
381
- this .handlerMethods = methods ;
382
- this .handlerMessageMethods = messageMethods ;
383
- this .handlerMethodsList = new LinkedList <>();
384
-
385
- //TODO Consider to use global option to determine a precedence of methods
386
- this .handlerMethodsList .add (this .handlerMethods );
387
- this .handlerMethodsList .add (this .handlerMessageMethods );
388
- }
389
- setDisplayString (targetObject , methodName );
390
- JsonObjectMapper <?, ?> mapper ;
391
- try {
392
- mapper = JsonObjectMapperProvider .newInstance ();
393
- }
394
- catch (IllegalStateException e ) {
395
- mapper = null ;
396
- }
397
- this .jsonObjectMapper = mapper ;
398
- }
399
-
400
398
private boolean isProvidedMessageHandlerFactoryBean () {
401
399
BeanFactory beanFactory = getBeanFactory ();
402
400
return beanFactory != null
403
401
&& beanFactory .containsBean (IntegrationContextUtils .MESSAGE_HANDLER_FACTORY_BEAN_NAME );
404
402
}
405
403
406
- private void createHandlerMethod () {
404
+ private HandlerMethod createHandlerMethod (Method method ) {
407
405
try {
408
- InvocableHandlerMethod invocableHandlerMethod =
409
- this .messageHandlerMethodFactory .createInvocableHandlerMethod (this .targetObject , this .method );
410
- this .handlerMethod = new HandlerMethod (invocableHandlerMethod , this .canProcessMessageList );
411
- this .defaultHandlerMethod = null ;
412
- checkSpelInvokerRequired (getTargetClass (this .targetObject ), this .method , this .handlerMethod );
406
+ InvocableHandlerMethod invocableHandlerMethod = createInvocableHandlerMethod (method );
407
+ HandlerMethod handlerMethod = new HandlerMethod (invocableHandlerMethod , this .canProcessMessageList );
408
+ checkSpelInvokerRequired (getTargetClass (this .targetObject ), method , handlerMethod );
409
+ return handlerMethod ;
413
410
}
414
411
catch (IneligibleMethodException e ) {
415
412
throw new IllegalArgumentException (e );
416
413
}
417
414
}
418
415
416
+ private InvocableHandlerMethod createInvocableHandlerMethod (Method method ) {
417
+ return this .messageHandlerMethodFactory .createInvocableHandlerMethod (this .targetObject , method );
418
+ }
419
+
419
420
private void setDisplayString (Object targetObject , Object targetMethod ) {
420
421
StringBuilder sb = new StringBuilder (targetObject .getClass ().getName ());
421
422
if (targetMethod instanceof Method ) {
@@ -472,7 +473,7 @@ private T processInternal(ParametersWrapper parameters) throws Exception {
472
473
if (!this .initialized ) {
473
474
initialize ();
474
475
}
475
- HandlerMethod candidate = this . findHandlerMethodForParameters (parameters );
476
+ HandlerMethod candidate = findHandlerMethodForParameters (parameters );
476
477
if (candidate == null ) {
477
478
candidate = this .defaultHandlerMethod ;
478
479
}
@@ -525,7 +526,13 @@ private synchronized void initialize() throws Exception {
525
526
this .messageHandlerMethodFactory =
526
527
beanFactory .getBean (IntegrationContextUtils .MESSAGE_HANDLER_FACTORY_BEAN_NAME ,
527
528
MessageHandlerMethodFactory .class );
528
- createHandlerMethod ();
529
+ this .handlerMethodsList
530
+ .stream ()
531
+ .map (Map ::values )
532
+ .flatMap (Collection ::stream )
533
+ .forEach (handlerMethod ->
534
+ handlerMethod .replaceInvocableHandlerMethod (
535
+ createInvocableHandlerMethod (handlerMethod .invocableHandlerMethod .getMethod ())));
529
536
}
530
537
else {
531
538
if (beanFactory != null &&
@@ -645,7 +652,6 @@ else if (e instanceof IllegalStateException) {
645
652
expression .getExpressionString () + " ]" );
646
653
}
647
654
}
648
-
649
655
return invokeExpression (expression , parameters );
650
656
}
651
657
}
@@ -716,9 +722,8 @@ private boolean contentTypeIsJson(Message<?> message) {
716
722
return contentType != null && contentType .toString ().contains ("json" );
717
723
}
718
724
719
- private Map <String , Map <Class <?>, HandlerMethod >> findHandlerMethodsForTarget (final Object targetObject ,
720
- final Class <? extends Annotation > annotationType , final String methodNameArg ,
721
- final boolean requiresReply ) {
725
+ private Map <String , Map <Class <?>, HandlerMethod >> findHandlerMethodsForTarget (
726
+ final Class <? extends Annotation > annotationType , final String methodNameArg , final boolean requiresReply ) {
722
727
723
728
Map <String , Map <Class <?>, HandlerMethod >> methods = new HashMap <>();
724
729
@@ -728,7 +733,7 @@ private Map<String, Map<Class<?>, HandlerMethod>> findHandlerMethodsForTarget(fi
728
733
final Map <Class <?>, HandlerMethod > fallbackMessageMethods = new HashMap <>();
729
734
final AtomicReference <Class <?>> ambiguousFallbackType = new AtomicReference <>();
730
735
final AtomicReference <Class <?>> ambiguousFallbackMessageGenericType = new AtomicReference <>();
731
- final Class <?> targetClass = getTargetClass (targetObject );
736
+ final Class <?> targetClass = getTargetClass (this . targetObject );
732
737
733
738
final String methodNameToUse ;
734
739
@@ -779,11 +784,8 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
779
784
HandlerMethod handlerMethod1 ;
780
785
try {
781
786
method1 = AopUtils .selectInvocableMethod (method1 ,
782
- org .springframework .util .ClassUtils .getUserClass (targetObject ));
783
- InvocableHandlerMethod invocableHandlerMethod =
784
- this .messageHandlerMethodFactory .createInvocableHandlerMethod (targetObject , method1 );
785
- handlerMethod1 = new HandlerMethod (invocableHandlerMethod , this .canProcessMessageList );
786
- checkSpelInvokerRequired (targetClass , method1 , handlerMethod1 );
787
+ org .springframework .util .ClassUtils .getUserClass (this .targetObject ));
788
+ handlerMethod1 = createHandlerMethod (method1 );
787
789
}
788
790
catch (IneligibleMethodException e ) {
789
791
if (logger .isDebugEnabled ()) {
@@ -800,7 +802,7 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
800
802
}
801
803
if (AnnotationUtils .getAnnotation (method1 , Default .class ) != null ) {
802
804
Assert .state (this .defaultHandlerMethod == null ,
803
- () -> "Only one method can be @Default, but there are more for: " + targetObject );
805
+ () -> "Only one method can be @Default, but there are more for: " + this . targetObject );
804
806
this .defaultHandlerMethod = handlerMethod1 ;
805
807
}
806
808
Class <?> targetParameterType = handlerMethod1 .getTargetParameterType ();
@@ -850,8 +852,7 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
850
852
851
853
if (candidateMethods .isEmpty () && candidateMessageMethods .isEmpty () && fallbackMethods .isEmpty ()
852
854
&& fallbackMessageMethods .isEmpty ()) {
853
- findSingleSpecifMethodOnInterfacesIfProxy (targetObject , methodNameToUse , candidateMessageMethods ,
854
- candidateMethods );
855
+ findSingleSpecifMethodOnInterfacesIfProxy (methodNameToUse , candidateMessageMethods , candidateMethods );
855
856
}
856
857
857
858
if (!candidateMethods .isEmpty () || !candidateMessageMethods .isEmpty ()) {
@@ -875,7 +876,7 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
875
876
if ("org.springframework.integration.gateway.RequestReplyExchanger" .equals (iface .getName ())) {
876
877
frameworkMethods .add (targetClass .getMethod ("exchange" , Message .class ));
877
878
if (logger .isDebugEnabled ()) {
878
- logger .debug (targetObject .getClass () +
879
+ logger .debug (this . targetObject .getClass () +
879
880
": Ambiguous fallback methods; using RequestReplyExchanger.exchange()" );
880
881
}
881
882
}
@@ -886,12 +887,8 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
886
887
}
887
888
if (frameworkMethods .size () == 1 ) {
888
889
Method frameworkMethod = org .springframework .util .ClassUtils .getMostSpecificMethod (
889
- frameworkMethods .get (0 ), targetObject .getClass ());
890
- InvocableHandlerMethod invocableHandlerMethod =
891
- this .messageHandlerMethodFactory .createInvocableHandlerMethod (targetObject ,
892
- frameworkMethod );
893
- HandlerMethod theHandlerMethod = new HandlerMethod (invocableHandlerMethod , this .canProcessMessageList );
894
- checkSpelInvokerRequired (targetClass , frameworkMethod , theHandlerMethod );
890
+ frameworkMethods .get (0 ), this .targetObject .getClass ());
891
+ HandlerMethod theHandlerMethod = createHandlerMethod (frameworkMethod );
895
892
methods .put (CANDIDATE_METHODS , Collections .singletonMap (Object .class , theHandlerMethod ));
896
893
methods .put (CANDIDATE_MESSAGE_METHODS , candidateMessageMethods );
897
894
return methods ;
@@ -916,17 +913,17 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
916
913
return methods ;
917
914
}
918
915
919
- private void findSingleSpecifMethodOnInterfacesIfProxy (final Object targetObject , final String methodName ,
916
+ private void findSingleSpecifMethodOnInterfacesIfProxy (final String methodName ,
920
917
Map <Class <?>, HandlerMethod > candidateMessageMethods ,
921
918
Map <Class <?>, HandlerMethod > candidateMethods ) {
922
- if (AopUtils .isAopProxy (targetObject )) {
919
+ if (AopUtils .isAopProxy (this . targetObject )) {
923
920
final AtomicReference <Method > targetMethod = new AtomicReference <>();
924
921
final AtomicReference <Class <?>> targetClass = new AtomicReference <>();
925
- Class <?>[] interfaces = ((Advised ) targetObject ).getProxiedInterfaces ();
922
+ Class <?>[] interfaces = ((Advised ) this . targetObject ).getProxiedInterfaces ();
926
923
for (Class <?> clazz : interfaces ) {
927
924
ReflectionUtils .doWithMethods (clazz , method1 -> {
928
925
if (targetMethod .get () != null ) {
929
- throw new IllegalStateException ("Ambiguous method " + methodName + " on " + targetObject );
926
+ throw new IllegalStateException ("Ambiguous method " + methodName + " on " + this . targetObject );
930
927
}
931
928
else {
932
929
targetMethod .set (method1 );
@@ -937,11 +934,8 @@ private void findSingleSpecifMethodOnInterfacesIfProxy(final Object targetObject
937
934
Method theMethod = targetMethod .get ();
938
935
if (theMethod != null ) {
939
936
theMethod = org .springframework .util .ClassUtils
940
- .getMostSpecificMethod (theMethod , targetObject .getClass ());
941
- InvocableHandlerMethod invocableHandlerMethod =
942
- this .messageHandlerMethodFactory .createInvocableHandlerMethod (targetObject , theMethod );
943
- HandlerMethod theHandlerMethod = new HandlerMethod (invocableHandlerMethod , this .canProcessMessageList );
944
- checkSpelInvokerRequired (targetClass .get (), theMethod , theHandlerMethod );
937
+ .getMostSpecificMethod (theMethod , this .targetObject .getClass ());
938
+ HandlerMethod theHandlerMethod = createHandlerMethod (theMethod );
945
939
Class <?> targetParameterType = theHandlerMethod .getTargetParameterType ();
946
940
if (theHandlerMethod .isMessageMethod ()) {
947
941
if (candidateMessageMethods .containsKey (targetParameterType )) {
@@ -1033,7 +1027,7 @@ private HandlerMethod findHandlerMethodForParameters(ParametersWrapper parameter
1033
1027
1034
1028
final Class <?> payloadType = parameters .getFirstParameterType ();
1035
1029
1036
- HandlerMethod closestMatch = this . findClosestMatch (payloadType );
1030
+ HandlerMethod closestMatch = findClosestMatch (payloadType );
1037
1031
if (closestMatch != null ) {
1038
1032
return closestMatch ;
1039
1033
@@ -1045,7 +1039,6 @@ private HandlerMethod findHandlerMethodForParameters(ParametersWrapper parameter
1045
1039
else {
1046
1040
return this .handlerMethods .get (Void .class );
1047
1041
}
1048
-
1049
1042
}
1050
1043
1051
1044
private HandlerMethod findClosestMatch (Class <?> payloadType ) {
@@ -1078,10 +1071,10 @@ private static class HandlerMethod {
1078
1071
1079
1072
private final String expressionString ;
1080
1073
1081
- private final InvocableHandlerMethod invocableHandlerMethod ;
1082
-
1083
1074
private final boolean canProcessMessageList ;
1084
1075
1076
+ private InvocableHandlerMethod invocableHandlerMethod ;
1077
+
1085
1078
private volatile Expression expression ;
1086
1079
1087
1080
private volatile TypeDescriptor targetParameterTypeDescriptor ;
@@ -1109,6 +1102,9 @@ private static class HandlerMethod {
1109
1102
this .expressionString = generateExpression (this .invocableHandlerMethod .getMethod ());
1110
1103
}
1111
1104
1105
+ void replaceInvocableHandlerMethod (InvocableHandlerMethod newInvocableHandlerMethod ) {
1106
+ this .invocableHandlerMethod = newInvocableHandlerMethod ;
1107
+ }
1112
1108
1113
1109
@ SuppressWarnings ("unchecked" )
1114
1110
public <T > T invoke (ParametersWrapper parameters ) throws Exception {
0 commit comments