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:
Mark Fisher
2008-10-14 14:16:49 +00:00
parent b7f4c1c1e9
commit 79d9d8dc07
9 changed files with 122 additions and 7 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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;
}
}
}