From 9b301bf19f6c378f7df74366789fd92a9f0dcfcb Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 4 Feb 2010 19:42:25 +0000 Subject: [PATCH] INT-981 Added MethodFilter to be invoked by ReflectionUtils.doWithMethods(..) --- .../MethodInvokingMessageProcessor.java | 29 ++++++-- .../MethodInvokingMessageProcessorTests.java | 74 +++++++++++++++++++ 2 files changed, 98 insertions(+), 5 deletions(-) diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodInvokingMessageProcessor.java b/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodInvokingMessageProcessor.java index 6154359153..66f1b676f6 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodInvokingMessageProcessor.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodInvokingMessageProcessor.java @@ -20,6 +20,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -30,7 +31,6 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.springframework.aop.support.AopUtils; import org.springframework.context.expression.MapAccessor; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; @@ -56,9 +56,11 @@ import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import org.springframework.util.ReflectionUtils.MethodCallback; +import org.springframework.util.ReflectionUtils.MethodFilter; /** * @author Mark Fisher + * @author Oleg Zhurakousky * @since 2.0 */ public class MethodInvokingMessageProcessor implements MessageProcessor { @@ -142,7 +144,7 @@ public class MethodInvokingMessageProcessor implements MessageProcessor { new FixedHandlerMethodFilter((Method) method), targetType)); } else if (method == null || method instanceof String) { - context.getMethodResolvers().add(new FilteringReflectiveMethodResolver( + context.getMethodResolvers().add(new FilteringReflectiveMethodResolver( new HandlerMethodFilter(annotationType, (String) method, this.requiresReply), targetType)); } context.addPropertyAccessor(new MapAccessor()); @@ -192,7 +194,8 @@ public class MethodInvokingMessageProcessor implements MessageProcessor { final Map, HandlerMethod> candidateMethods = new HashMap, HandlerMethod>(); final Map, HandlerMethod> fallbackMethods = new HashMap, HandlerMethod>(); final AtomicReference> ambiguousFallbackType = new AtomicReference>(); - Class targetClass = this.getTargetClass(targetObject); + final Class targetClass = this.getTargetClass(targetObject); + MethodFilter methodFilter = new UniqueMethodFilter(targetClass); ReflectionUtils.doWithMethods(targetClass, new MethodCallback() { public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { boolean matchesAnnotation = false; @@ -240,7 +243,7 @@ public class MethodInvokingMessageProcessor implements MessageProcessor { fallbackMethods.put(targetParameterType, handlerMethod); } } - }); + }, methodFilter); if (!candidateMethods.isEmpty()) { return candidateMethods; } @@ -445,5 +448,21 @@ public class MethodInvokingMessageProcessor implements MessageProcessor { this.targetParameterType = targetParameterType; } } - + /** + * @author Oleg Zhurakousky + * @since 2.0 + */ + private class UniqueMethodFilter implements MethodFilter { + private List uniqueMethods = new ArrayList(); + + public UniqueMethodFilter(Class targetClass){ + ArrayList allMethods = new ArrayList(Arrays.asList(targetClass.getMethods())); + for (Method method : allMethods) { + uniqueMethods.add(org.springframework.util.ClassUtils.getMostSpecificMethod(method, targetClass)); + } + } + public boolean matches(Method method) { + return uniqueMethods.contains(method); + } + } } diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java index cfd06af6b3..ccb5a1070b 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java @@ -38,9 +38,82 @@ import org.springframework.integration.message.StringMessage; /** * @author Mark Fisher * @author Marius Bogoevici + * @author Oleg Zhurakousky */ public class MethodInvokingMessageProcessorTests { + @Test + public void testHandlerInheritanceMethodImplInSuper() { + class A{ + public Message myMethod(final Message msg){ + return MessageBuilder.fromMessage(msg).setHeader("A", "A").build(); + } + } + class B extends A{} + class C extends B{} + MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor( + new B(), "myMethod"); + Message message = (Message) processor.processMessage(new StringMessage("")); + assertEquals("A", message.getHeaders().get("A")); + } + @Test + public void testHandlerInheritanceMethodImplInLatestSuper() { + class A{ + public Message myMethod(Message msg){ + return MessageBuilder.fromMessage(msg).setHeader("A", "A").build(); + } + } + class B extends A{ + public Message myMethod(Message msg){ + return MessageBuilder.fromMessage(msg).setHeader("B", "B").build(); + } + } + class C extends B{} + MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor( + new B(), "myMethod"); + Message message = (Message) processor.processMessage(new StringMessage("")); + assertEquals("B", message.getHeaders().get("B")); + } + + public void testHandlerInheritanceMethodImplInSubClass() { + class A{ + public Message myMethod(Message msg){ + return MessageBuilder.fromMessage(msg).setHeader("A", "A").build(); + } + } + class B extends A{ + public Message myMethod(Message msg){ + return MessageBuilder.fromMessage(msg).setHeader("B", "B").build(); + } + } + class C extends B{ + public Message myMethod(Message msg){ + return MessageBuilder.fromMessage(msg).setHeader("C", "C").build(); + } + } + MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor( + new C(), "myMethod"); + Message message = (Message) processor.processMessage(new StringMessage("")); + assertEquals("C", message.getHeaders().get("C")); + } + public void testHandlerInheritanceMethodImplInSubClassAndSuper() { + class A{ + public Message myMethod(Message msg){ + return MessageBuilder.fromMessage(msg).setHeader("A", "A").build(); + } + } + class B extends A{} + class C extends B{ + public Message myMethod(Message msg){ + return MessageBuilder.fromMessage(msg).setHeader("C", "C").build(); + } + } + MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor( + new C(), "myMethod"); + Message message = (Message) processor.processMessage(new StringMessage("")); + assertEquals("C", message.getHeaders().get("C")); + } + @Test public void payloadAsMethodParameterAndObjectAsReturnValue() { MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor( @@ -198,6 +271,7 @@ public class MethodInvokingMessageProcessorTests { assertEquals(String.class, bean.lastArg.getClass()); assertEquals("true", bean.lastArg); } + @SuppressWarnings("unused")