@@ -175,7 +175,7 @@ public class MessagingMethodInvokerHelper extends AbstractExpressionEvaluator im
175
175
176
176
private final Map <Class <?>, HandlerMethod > handlerMessageMethods ;
177
177
178
- private final List <Map <Class <?>, HandlerMethod >> handlerMethodsList ;
178
+ private final List <Map <Class <?>, HandlerMethod >> handlerMethodsList = new LinkedList <>() ;
179
179
180
180
private final TypeDescriptor expectedType ;
181
181
@@ -254,10 +254,11 @@ private MessagingMethodInvokerHelper(Object targetObject, Class<? extends Annota
254
254
255
255
Assert .notNull (targetObject , "targetObject must not be null" );
256
256
this .targetObject = targetObject ;
257
- createHandlerMethod ();
257
+ this . handlerMethod = createHandlerMethod (this . method );
258
258
this .handlerMethods = null ;
259
259
this .handlerMessageMethods = null ;
260
- this .handlerMethodsList = null ;
260
+ this .handlerMethodsList .add (
261
+ Collections .singletonMap (this .handlerMethod .targetParameterType , this .handlerMethod ));
261
262
setDisplayString (targetObject , method );
262
263
263
264
JsonObjectMapper <?, ?> mapper ;
@@ -270,6 +271,54 @@ private MessagingMethodInvokerHelper(Object targetObject, Class<? extends Annota
270
271
this .jsonObjectMapper = mapper ;
271
272
}
272
273
274
+ private MessagingMethodInvokerHelper (Object targetObject , Class <? extends Annotation > annotationType ,
275
+ String methodName , Class <?> expectedType , boolean canProcessMessageList ) {
276
+
277
+ this .annotationType = annotationType ;
278
+ this .methodName = methodName ;
279
+ this .canProcessMessageList = canProcessMessageList ;
280
+ Assert .notNull (targetObject , "targetObject must not be null" );
281
+ if (expectedType != null ) {
282
+ this .expectedType = TypeDescriptor .valueOf (expectedType );
283
+ }
284
+ else {
285
+ this .expectedType = null ;
286
+ }
287
+ this .targetObject = targetObject ;
288
+ Map <String , Map <Class <?>, HandlerMethod >> handlerMethodsForTarget =
289
+ findHandlerMethodsForTarget (annotationType , methodName , expectedType != null );
290
+ Map <Class <?>, HandlerMethod > methods = handlerMethodsForTarget .get (CANDIDATE_METHODS );
291
+ Map <Class <?>, HandlerMethod > messageMethods = handlerMethodsForTarget .get (CANDIDATE_MESSAGE_METHODS );
292
+ if ((methods .size () == 1 && messageMethods .isEmpty ()) ||
293
+ (messageMethods .size () == 1 && methods .isEmpty ())) {
294
+ if (methods .size () == 1 ) {
295
+ this .handlerMethod = methods .values ().iterator ().next ();
296
+ }
297
+ else {
298
+ this .handlerMethod = messageMethods .values ().iterator ().next ();
299
+ }
300
+ }
301
+ else {
302
+ this .handlerMethod = null ;
303
+ }
304
+
305
+ this .handlerMethods = methods ;
306
+ this .handlerMessageMethods = messageMethods ;
307
+ //TODO Consider to use global option to determine a precedence of methods
308
+ this .handlerMethodsList .add (this .handlerMethods );
309
+ this .handlerMethodsList .add (this .handlerMessageMethods );
310
+
311
+ setDisplayString (targetObject , methodName );
312
+ JsonObjectMapper <?, ?> mapper ;
313
+ try {
314
+ mapper = JsonObjectMapperProvider .newInstance ();
315
+ }
316
+ catch (IllegalStateException e ) {
317
+ mapper = null ;
318
+ }
319
+ this .jsonObjectMapper = mapper ;
320
+ }
321
+
273
322
/**
274
323
* A {@code boolean} flag to use SpEL Expression evaluation or {@link InvocableHandlerMethod}
275
324
* for target method invocation.
@@ -344,76 +393,28 @@ public boolean isRunning() {
344
393
* Private constructors for internal use
345
394
*/
346
395
347
- private MessagingMethodInvokerHelper (Object targetObject , Class <? extends Annotation > annotationType ,
348
- String methodName , Class <?> expectedType , boolean canProcessMessageList ) {
349
-
350
- this .annotationType = annotationType ;
351
- this .methodName = methodName ;
352
- this .canProcessMessageList = canProcessMessageList ;
353
- Assert .notNull (targetObject , "targetObject must not be null" );
354
- if (expectedType != null ) {
355
- this .expectedType = TypeDescriptor .valueOf (expectedType );
356
- }
357
- else {
358
- this .expectedType = null ;
359
- }
360
- this .targetObject = targetObject ;
361
- Map <String , Map <Class <?>, HandlerMethod >> handlerMethodsForTarget =
362
- findHandlerMethodsForTarget (targetObject , annotationType , methodName , expectedType != null );
363
- Map <Class <?>, HandlerMethod > methods = handlerMethodsForTarget .get (CANDIDATE_METHODS );
364
- Map <Class <?>, HandlerMethod > messageMethods = handlerMethodsForTarget .get (CANDIDATE_MESSAGE_METHODS );
365
- if ((methods .size () == 1 && messageMethods .isEmpty ()) ||
366
- (messageMethods .size () == 1 && methods .isEmpty ())) {
367
- if (methods .size () == 1 ) {
368
- this .handlerMethod = methods .values ().iterator ().next ();
369
- }
370
- else {
371
- this .handlerMethod = messageMethods .values ().iterator ().next ();
372
- }
373
- this .handlerMethods = null ;
374
- this .handlerMessageMethods = null ;
375
- this .handlerMethodsList = null ;
376
- }
377
- else {
378
- this .handlerMethod = null ;
379
- this .handlerMethods = methods ;
380
- this .handlerMessageMethods = messageMethods ;
381
- this .handlerMethodsList = new LinkedList <>();
382
-
383
- //TODO Consider to use global option to determine a precedence of methods
384
- this .handlerMethodsList .add (this .handlerMethods );
385
- this .handlerMethodsList .add (this .handlerMessageMethods );
386
- }
387
- setDisplayString (targetObject , methodName );
388
- JsonObjectMapper <?, ?> mapper ;
389
- try {
390
- mapper = JsonObjectMapperProvider .newInstance ();
391
- }
392
- catch (IllegalStateException e ) {
393
- mapper = null ;
394
- }
395
- this .jsonObjectMapper = mapper ;
396
- }
397
-
398
396
private boolean isProvidedMessageHandlerFactoryBean () {
399
397
BeanFactory beanFactory = getBeanFactory ();
400
398
return beanFactory != null
401
399
&& beanFactory .containsBean (IntegrationContextUtils .MESSAGE_HANDLER_FACTORY_BEAN_NAME );
402
400
}
403
401
404
- private void createHandlerMethod () {
402
+ private HandlerMethod createHandlerMethod (Method method ) {
405
403
try {
406
- InvocableHandlerMethod invocableHandlerMethod =
407
- this .messageHandlerMethodFactory .createInvocableHandlerMethod (this .targetObject , this .method );
408
- this .handlerMethod = new HandlerMethod (invocableHandlerMethod , this .canProcessMessageList );
409
- this .defaultHandlerMethod = null ;
410
- checkSpelInvokerRequired (getTargetClass (this .targetObject ), this .method , this .handlerMethod );
404
+ InvocableHandlerMethod invocableHandlerMethod = createInvocableHandlerMethod (method );
405
+ HandlerMethod handlerMethod = new HandlerMethod (invocableHandlerMethod , this .canProcessMessageList );
406
+ checkSpelInvokerRequired (getTargetClass (this .targetObject ), method , handlerMethod );
407
+ return handlerMethod ;
411
408
}
412
409
catch (IneligibleMethodException e ) {
413
410
throw new IllegalArgumentException (e );
414
411
}
415
412
}
416
413
414
+ private InvocableHandlerMethod createInvocableHandlerMethod (Method method ) {
415
+ return this .messageHandlerMethodFactory .createInvocableHandlerMethod (this .targetObject , method );
416
+ }
417
+
417
418
private void setDisplayString (Object targetObject , Object targetMethod ) {
418
419
StringBuilder sb = new StringBuilder (targetObject .getClass ().getName ());
419
420
if (targetMethod instanceof Method ) {
@@ -475,7 +476,7 @@ private Object processInternal(ParametersWrapper parameters) {
475
476
if (!this .initialized ) {
476
477
initialize ();
477
478
}
478
- HandlerMethod candidate = this . findHandlerMethodForParameters (parameters );
479
+ HandlerMethod candidate = findHandlerMethodForParameters (parameters );
479
480
if (candidate == null ) {
480
481
candidate = this .defaultHandlerMethod ;
481
482
}
@@ -528,7 +529,13 @@ private synchronized void initialize() {
528
529
this .messageHandlerMethodFactory =
529
530
beanFactory .getBean (IntegrationContextUtils .MESSAGE_HANDLER_FACTORY_BEAN_NAME ,
530
531
MessageHandlerMethodFactory .class );
531
- createHandlerMethod ();
532
+ this .handlerMethodsList
533
+ .stream ()
534
+ .map (Map ::values )
535
+ .flatMap (Collection ::stream )
536
+ .forEach (handlerMethod ->
537
+ handlerMethod .replaceInvocableHandlerMethod (
538
+ createInvocableHandlerMethod (handlerMethod .invocableHandlerMethod .getMethod ())));
532
539
}
533
540
else {
534
541
if (beanFactory != null &&
@@ -648,11 +655,11 @@ private Object processInvokeExceptionAndFallbackToExpressionIfAny(HandlerMethod
648
655
}
649
656
else if (ex instanceof IllegalStateException && // NOSONAR complex boolean expression
650
657
(!(ex .getCause () instanceof IllegalArgumentException ) ||
651
- !ex .getStackTrace ()[0 ].getClassName ().equals (InvocableHandlerMethod .class .getName ()) ||
652
- (!"argument type mismatch" .equals (ex .getCause ().getMessage ()) &&
653
- // JVM generates GeneratedMethodAccessor### after several calls with less error
654
- // checking
655
- !ex .getCause ().getMessage ().startsWith ("java.lang.ClassCastException@" )))) {
658
+ !ex .getStackTrace ()[0 ].getClassName ().equals (InvocableHandlerMethod .class .getName ()) ||
659
+ (!"argument type mismatch" .equals (ex .getCause ().getMessage ()) &&
660
+ // JVM generates GeneratedMethodAccessor### after several calls with less error
661
+ // checking
662
+ !ex .getCause ().getMessage ().startsWith ("java.lang.ClassCastException@" )))) {
656
663
throw ex ;
657
664
}
658
665
@@ -746,9 +753,8 @@ private boolean contentTypeIsJson(Message<?> message) {
746
753
return contentType != null && contentType .toString ().contains ("json" );
747
754
}
748
755
749
- private Map <String , Map <Class <?>, HandlerMethod >> findHandlerMethodsForTarget (final Object targetObject ,
750
- final Class <? extends Annotation > annotationType , final String methodNameArg ,
751
- final boolean requiresReply ) {
756
+ private Map <String , Map <Class <?>, HandlerMethod >> findHandlerMethodsForTarget (
757
+ final Class <? extends Annotation > annotationType , final String methodNameArg , final boolean requiresReply ) {
752
758
753
759
Map <String , Map <Class <?>, HandlerMethod >> methods = new HashMap <>();
754
760
@@ -758,7 +764,7 @@ private Map<String, Map<Class<?>, HandlerMethod>> findHandlerMethodsForTarget(fi
758
764
final Map <Class <?>, HandlerMethod > fallbackMessageMethods = new HashMap <>();
759
765
final AtomicReference <Class <?>> ambiguousFallbackType = new AtomicReference <>();
760
766
final AtomicReference <Class <?>> ambiguousFallbackMessageGenericType = new AtomicReference <>();
761
- final Class <?> targetClass = getTargetClass (targetObject );
767
+ final Class <?> targetClass = getTargetClass (this . targetObject );
762
768
763
769
final String methodNameToUse ;
764
770
@@ -809,11 +815,8 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
809
815
HandlerMethod handlerMethod1 ;
810
816
try {
811
817
method1 = AopUtils .selectInvocableMethod (method1 ,
812
- org .springframework .util .ClassUtils .getUserClass (targetObject ));
813
- InvocableHandlerMethod invocableHandlerMethod =
814
- this .messageHandlerMethodFactory .createInvocableHandlerMethod (targetObject , method1 );
815
- handlerMethod1 = new HandlerMethod (invocableHandlerMethod , this .canProcessMessageList );
816
- checkSpelInvokerRequired (targetClass , method1 , handlerMethod1 );
818
+ org .springframework .util .ClassUtils .getUserClass (this .targetObject ));
819
+ handlerMethod1 = createHandlerMethod (method1 );
817
820
}
818
821
catch (IneligibleMethodException e ) {
819
822
if (LOGGER .isDebugEnabled ()) {
@@ -830,7 +833,7 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
830
833
}
831
834
if (AnnotationUtils .getAnnotation (method1 , Default .class ) != null ) {
832
835
Assert .state (this .defaultHandlerMethod == null ,
833
- () -> "Only one method can be @Default, but there are more for: " + targetObject );
836
+ () -> "Only one method can be @Default, but there are more for: " + this . targetObject );
834
837
this .defaultHandlerMethod = handlerMethod1 ;
835
838
}
836
839
Class <?> targetParameterType = handlerMethod1 .getTargetParameterType ();
@@ -880,8 +883,7 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
880
883
881
884
if (candidateMethods .isEmpty () && candidateMessageMethods .isEmpty () && fallbackMethods .isEmpty ()
882
885
&& fallbackMessageMethods .isEmpty ()) {
883
- findSingleSpecifMethodOnInterfacesIfProxy (targetObject , methodNameToUse , candidateMessageMethods ,
884
- candidateMethods );
886
+ findSingleSpecifMethodOnInterfacesIfProxy (methodNameToUse , candidateMessageMethods , candidateMethods );
885
887
}
886
888
887
889
if (!candidateMethods .isEmpty () || !candidateMessageMethods .isEmpty ()) {
@@ -905,7 +907,7 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
905
907
if ("org.springframework.integration.gateway.RequestReplyExchanger" .equals (iface .getName ())) {
906
908
frameworkMethods .add (targetClass .getMethod ("exchange" , Message .class ));
907
909
if (LOGGER .isDebugEnabled ()) {
908
- LOGGER .debug (targetObject .getClass () +
910
+ LOGGER .debug (this . targetObject .getClass () +
909
911
": Ambiguous fallback methods; using RequestReplyExchanger.exchange()" );
910
912
}
911
913
}
@@ -916,12 +918,8 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
916
918
}
917
919
if (frameworkMethods .size () == 1 ) {
918
920
Method frameworkMethod = org .springframework .util .ClassUtils .getMostSpecificMethod (
919
- frameworkMethods .get (0 ), targetObject .getClass ());
920
- InvocableHandlerMethod invocableHandlerMethod =
921
- this .messageHandlerMethodFactory .createInvocableHandlerMethod (targetObject ,
922
- frameworkMethod );
923
- HandlerMethod theHandlerMethod = new HandlerMethod (invocableHandlerMethod , this .canProcessMessageList );
924
- checkSpelInvokerRequired (targetClass , frameworkMethod , theHandlerMethod );
921
+ frameworkMethods .get (0 ), this .targetObject .getClass ());
922
+ HandlerMethod theHandlerMethod = createHandlerMethod (frameworkMethod );
925
923
methods .put (CANDIDATE_METHODS , Collections .singletonMap (Object .class , theHandlerMethod ));
926
924
methods .put (CANDIDATE_MESSAGE_METHODS , candidateMessageMethods );
927
925
return methods ;
@@ -946,17 +944,17 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
946
944
return methods ;
947
945
}
948
946
949
- private void findSingleSpecifMethodOnInterfacesIfProxy (final Object targetObject , final String methodName ,
947
+ private void findSingleSpecifMethodOnInterfacesIfProxy (final String methodName ,
950
948
Map <Class <?>, HandlerMethod > candidateMessageMethods ,
951
949
Map <Class <?>, HandlerMethod > candidateMethods ) {
952
- if (AopUtils .isAopProxy (targetObject )) {
950
+ if (AopUtils .isAopProxy (this . targetObject )) {
953
951
final AtomicReference <Method > targetMethod = new AtomicReference <>();
954
952
final AtomicReference <Class <?>> targetClass = new AtomicReference <>();
955
- Class <?>[] interfaces = ((Advised ) targetObject ).getProxiedInterfaces ();
953
+ Class <?>[] interfaces = ((Advised ) this . targetObject ).getProxiedInterfaces ();
956
954
for (Class <?> clazz : interfaces ) {
957
955
ReflectionUtils .doWithMethods (clazz , method1 -> {
958
956
if (targetMethod .get () != null ) {
959
- throw new IllegalStateException ("Ambiguous method " + methodName + " on " + targetObject );
957
+ throw new IllegalStateException ("Ambiguous method " + methodName + " on " + this . targetObject );
960
958
}
961
959
else {
962
960
targetMethod .set (method1 );
@@ -967,11 +965,8 @@ private void findSingleSpecifMethodOnInterfacesIfProxy(final Object targetObject
967
965
Method theMethod = targetMethod .get ();
968
966
if (theMethod != null ) {
969
967
theMethod = org .springframework .util .ClassUtils
970
- .getMostSpecificMethod (theMethod , targetObject .getClass ());
971
- InvocableHandlerMethod invocableHandlerMethod =
972
- this .messageHandlerMethodFactory .createInvocableHandlerMethod (targetObject , theMethod );
973
- HandlerMethod theHandlerMethod = new HandlerMethod (invocableHandlerMethod , this .canProcessMessageList );
974
- checkSpelInvokerRequired (targetClass .get (), theMethod , theHandlerMethod );
968
+ .getMostSpecificMethod (theMethod , this .targetObject .getClass ());
969
+ HandlerMethod theHandlerMethod = createHandlerMethod (theMethod );
975
970
Class <?> targetParameterType = theHandlerMethod .getTargetParameterType ();
976
971
if (theHandlerMethod .isMessageMethod ()) {
977
972
if (candidateMessageMethods .containsKey (targetParameterType )) {
@@ -1064,7 +1059,7 @@ private HandlerMethod findHandlerMethodForParameters(ParametersWrapper parameter
1064
1059
1065
1060
final Class <?> payloadType = parameters .getFirstParameterType ();
1066
1061
1067
- HandlerMethod closestMatch = this . findClosestMatch (payloadType );
1062
+ HandlerMethod closestMatch = findClosestMatch (payloadType );
1068
1063
if (closestMatch != null ) {
1069
1064
return closestMatch ;
1070
1065
@@ -1076,7 +1071,6 @@ private HandlerMethod findHandlerMethodForParameters(ParametersWrapper parameter
1076
1071
else {
1077
1072
return this .handlerMethods .get (Void .class );
1078
1073
}
1079
-
1080
1074
}
1081
1075
1082
1076
private HandlerMethod findClosestMatch (Class <?> payloadType ) {
@@ -1109,10 +1103,10 @@ private static class HandlerMethod {
1109
1103
1110
1104
private final String expressionString ;
1111
1105
1112
- private final InvocableHandlerMethod invocableHandlerMethod ;
1113
-
1114
1106
private final boolean canProcessMessageList ;
1115
1107
1108
+ private InvocableHandlerMethod invocableHandlerMethod ;
1109
+
1116
1110
private volatile Expression expression ;
1117
1111
1118
1112
private volatile TypeDescriptor targetParameterTypeDescriptor ;
@@ -1140,6 +1134,9 @@ private static class HandlerMethod {
1140
1134
this .expressionString = generateExpression (this .invocableHandlerMethod .getMethod ());
1141
1135
}
1142
1136
1137
+ void replaceInvocableHandlerMethod (InvocableHandlerMethod newInvocableHandlerMethod ) {
1138
+ this .invocableHandlerMethod = newInvocableHandlerMethod ;
1139
+ }
1143
1140
1144
1141
public Object invoke (ParametersWrapper parameters ) {
1145
1142
Message <?> message = parameters .getMessage ();
0 commit comments