DefaultMethodResolver and AnnotationMethodResolver now use the target class of an AOP proxy. Added tests to DefaultMethodResolverTests: 'jdkProxy' and 'cglibProxy' (INT-425).
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 <em>single</em> 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 <code>null</code> 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 <em>single</em> 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<Method> annotatedMethod = new AtomicReference<Method>();
|
||||
ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 <code>null</code> 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 <em>single</em> 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 <code>null</code> 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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user