diff --git a/org.springframework.integration/.classpath b/org.springframework.integration/.classpath index 34c01dfac1..8cfdd6f039 100644 --- a/org.springframework.integration/.classpath +++ b/org.springframework.integration/.classpath @@ -4,6 +4,7 @@ + diff --git a/org.springframework.integration/ivy.xml b/org.springframework.integration/ivy.xml index 144dc2d43e..17ed703c40 100644 --- a/org.springframework.integration/ivy.xml +++ b/org.springframework.integration/ivy.xml @@ -20,6 +20,7 @@ + diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/aggregator/MethodInvokingAggregator.java b/org.springframework.integration/src/main/java/org/springframework/integration/aggregator/MethodInvokingAggregator.java index 289bb52f58..39cf23e45a 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/aggregator/MethodInvokingAggregator.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/aggregator/MethodInvokingAggregator.java @@ -52,7 +52,7 @@ public class MethodInvokingAggregator extends AbstractMessageAggregator { public MethodInvokingAggregator(Object object) { Assert.notNull(object, "object must not be null"); - Method method = this.methodResolver.findMethod(object.getClass()); + Method method = this.methodResolver.findMethod(object); Assert.notNull(method, "unable to resolve Aggregator method on target class [" + object.getClass() + "]"); this.methodInvoker = new MessageListMethodAdapter(object, method); diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/endpoint/ServiceActivatorEndpoint.java b/org.springframework.integration/src/main/java/org/springframework/integration/endpoint/ServiceActivatorEndpoint.java index 0f01982e08..64903ccb69 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/endpoint/ServiceActivatorEndpoint.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/endpoint/ServiceActivatorEndpoint.java @@ -45,7 +45,7 @@ public class ServiceActivatorEndpoint extends AbstractReplyProducingMessageConsu public ServiceActivatorEndpoint(final Object object) { Assert.notNull(object, "object must not be null"); - Method method = this.methodResolver.findMethod(object.getClass()); + Method method = this.methodResolver.findMethod(object); Assert.notNull(method, "unable to resolve ServiceActivator method on target class [" + object.getClass() + "]"); this.invoker = new MessageMappingMethodInvoker(object, method); diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/splitter/MethodInvokingSplitter.java b/org.springframework.integration/src/main/java/org/springframework/integration/splitter/MethodInvokingSplitter.java index e873e380e2..2a610d91a3 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/splitter/MethodInvokingSplitter.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/splitter/MethodInvokingSplitter.java @@ -52,7 +52,7 @@ public class MethodInvokingSplitter extends AbstractMessageSplitter implements I public MethodInvokingSplitter(Object object) { Assert.notNull(object, "object must not be null"); - Method method = this.methodResolver.findMethod(object.getClass()); + Method method = this.methodResolver.findMethod(object); Assert.notNull(method, "unable to resolve Splitter method on target class [" + object.getClass() + "]"); this.invoker = new MessageMappingMethodInvoker(object, method); diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/util/AnnotationMethodResolver.java b/org.springframework.integration/src/main/java/org/springframework/integration/util/AnnotationMethodResolver.java index 19c4a8cb69..85e777c1d1 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/util/AnnotationMethodResolver.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/util/AnnotationMethodResolver.java @@ -22,6 +22,7 @@ import java.lang.annotation.Target; import java.lang.reflect.Method; import java.util.concurrent.atomic.AtomicReference; +import org.springframework.aop.support.AopUtils; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -50,6 +51,29 @@ public class AnnotationMethodResolver implements MethodResolver { } + /** + * Find a single Method on the Class of the given candidate object + * that contains the annotation type for which this resolver is searching. + * + * @param candidate the instance whose Class will be checked for the + * annotation + * @param annotationType the Method-level annotation type + * + * @return a single matching Method instance or null if the + * candidate's Class contains no Methods with the specified annotation + * + * @throws IllegalArgumentException if more than one Method has the + * specified annotation + */ + public Method findMethod(Object candidate) { + Assert.notNull(candidate, "candidate object must not be null"); + Class targetClass = AopUtils.getTargetClass(candidate); + if (targetClass == null) { + targetClass = candidate.getClass(); + } + return this.findMethod(targetClass); + } + /** * Find a single Method on the given Class that contains the * annotation type for which this resolver is searching. @@ -64,6 +88,7 @@ public class AnnotationMethodResolver implements MethodResolver { * specified annotation */ public Method findMethod(final Class clazz) { + Assert.notNull(clazz, "class must not be null"); final AtomicReference annotatedMethod = new AtomicReference(); ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/util/DefaultMethodResolver.java b/org.springframework.integration/src/main/java/org/springframework/integration/util/DefaultMethodResolver.java index ed0c953021..67cd71e173 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/util/DefaultMethodResolver.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/util/DefaultMethodResolver.java @@ -19,6 +19,7 @@ package org.springframework.integration.util; import java.lang.annotation.Annotation; import java.lang.reflect.Method; +import org.springframework.aop.support.AopUtils; import org.springframework.util.Assert; /** @@ -43,8 +44,16 @@ public class DefaultMethodResolver implements MethodResolver { } + public Method findMethod(Object candidate) { + Assert.notNull(candidate, "candidate object must not be null"); + Class targetClass = AopUtils.getTargetClass(candidate); + if (targetClass == null) { + targetClass = candidate.getClass(); + } + return this.findMethod(targetClass); + } + public Method findMethod(Class clazz) { - Assert.notNull(clazz, "Class must not be null"); if (this.annotationMethodResolver != null) { Method method = this.annotationMethodResolver.findMethod(clazz); if (method != null) { diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/util/MethodResolver.java b/org.springframework.integration/src/main/java/org/springframework/integration/util/MethodResolver.java index ddbd4024da..84523cbedb 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/util/MethodResolver.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/util/MethodResolver.java @@ -26,10 +26,25 @@ import java.lang.reflect.Method; public interface MethodResolver { /** - * Find a single Method on the provided Class that matches this resolver's + * Find a single Method on the provided Object that matches this resolver's * criteria. * - * @param clazz the Class on which to search for a Method + * @param candidate the candidate Object whose Class should be searched for + * a Method + * + * @return a single Method or null if no Method matching this + * resolver's criteria can be found. + * + * @throws IllegalArgumentException if more than one Method defined on the + * given candidate's Class matches this resolver's criteria + */ + Method findMethod(Object candidate) throws IllegalArgumentException; + + /** + * Find a single Method on the given Class that matches this + * resolver's criteria. + * + * @param clazz the Class instance on which to search for a Method * * @return a single Method or null if no Method matching this * resolver's criteria can be found. @@ -37,6 +52,6 @@ public interface MethodResolver { * @throws IllegalArgumentException if more than one Method defined on the * given Class matches this resolver's criteria */ - Method findMethod(Class clazz) throws IllegalArgumentException; + Method findMethod(Class clazz); } diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/util/DefaultMethodResolverTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/util/DefaultMethodResolverTests.java index cef1bd7147..9161af8e5c 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/util/DefaultMethodResolverTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/util/DefaultMethodResolverTests.java @@ -16,6 +16,7 @@ package org.springframework.integration.util; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; @@ -27,6 +28,14 @@ import java.lang.reflect.Method; import org.junit.Test; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.endpoint.ServiceActivatorEndpoint; +import org.springframework.integration.endpoint.SubscribingConsumerEndpoint; +import org.springframework.integration.message.StringMessage; + /** * @author Mark Fisher */ @@ -65,6 +74,38 @@ public class DefaultMethodResolverTests { assertNull(method); } + @Test + public void jdkProxy() { + DirectChannel input = new DirectChannel(); + QueueChannel output = new QueueChannel(); + GreetingService testBean = new GreetingBean(); + ProxyFactory proxyFactory = new ProxyFactory(testBean); + proxyFactory.setProxyTargetClass(false); + testBean = (GreetingService) proxyFactory.getProxy(); + ServiceActivatorEndpoint consumer = new ServiceActivatorEndpoint(testBean); + consumer.setOutputChannel(output); + SubscribingConsumerEndpoint endpoint = new SubscribingConsumerEndpoint(consumer, input); + endpoint.start(); + input.send(new StringMessage("proxy")); + assertEquals("hello proxy", output.receive(0).getPayload());; + } + + @Test + public void cglibProxy() { + DirectChannel input = new DirectChannel(); + QueueChannel output = new QueueChannel(); + GreetingService testBean = new GreetingBean(); + ProxyFactory proxyFactory = new ProxyFactory(testBean); + proxyFactory.setProxyTargetClass(true); + testBean = (GreetingService) proxyFactory.getProxy(); + ServiceActivatorEndpoint consumer = new ServiceActivatorEndpoint(testBean); + consumer.setOutputChannel(output); + SubscribingConsumerEndpoint endpoint = new SubscribingConsumerEndpoint(consumer, input); + endpoint.start(); + input.send(new StringMessage("proxy")); + assertEquals("hello proxy", output.receive(0).getPayload());; + } + @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @@ -130,4 +171,27 @@ public class DefaultMethodResolverTests { } } + + public interface GreetingService { + + String sayHello(String s); + + } + + + public static class GreetingBean implements GreetingService { + + private String greeting = "hello"; + + public void setGreeting(String greeting) { + this.greeting = greeting; + } + + @ServiceActivator + public String sayHello(String name) { + return greeting + " " + name; + } + + } + }