Removed the MethodResolver interface and the DefaultMethodResolver and AnnotationMethodResolver classes. Only MethodInvokingAggregator was still using those, so that logic is now encapsulated there. If we find a need for this in the future, we can consider exposing it again, but for now it's less clutter for the API.

This commit is contained in:
Mark Fisher
2008-11-26 15:36:25 +00:00
parent 41eca0eb8a
commit 2c2a1be8ae
7 changed files with 253 additions and 545 deletions

View File

@@ -16,16 +16,19 @@
package org.springframework.integration.aggregator;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.springframework.aop.support.AopUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.integration.annotation.Aggregator;
import org.springframework.integration.core.Message;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.util.DefaultMethodResolver;
import org.springframework.integration.util.MethodResolver;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
/**
* {@link AbstractMessageAggregator} adapter for methods annotated with
@@ -37,8 +40,6 @@ import org.springframework.util.CollectionUtils;
*/
public class MethodInvokingAggregator extends AbstractMessageAggregator {
private final MethodResolver methodResolver = new DefaultMethodResolver(Aggregator.class);
private final MessageListMethodAdapter methodInvoker;
@@ -52,7 +53,7 @@ public class MethodInvokingAggregator extends AbstractMessageAggregator {
public MethodInvokingAggregator(Object object) {
Assert.notNull(object, "object must not be null");
Method method = this.methodResolver.findMethod(object);
Method method = this.findAggregatorMethod(object);
Assert.notNull(method, "unable to resolve Aggregator method on target class ["
+ object.getClass() + "]");
this.methodInvoker = new MessageListMethodAdapter(object, method);
@@ -73,4 +74,46 @@ public class MethodInvokingAggregator extends AbstractMessageAggregator {
return new GenericMessage<Object>(returnedValue);
}
private Method findAggregatorMethod(Object candidate) {
Class<?> targetClass = AopUtils.getTargetClass(candidate);
if (targetClass == null) {
targetClass = candidate.getClass();
}
Method method = this.findAnnotatedMethod(targetClass);
if (method == null) {
method = this.findSinglePublicMethod(targetClass);
}
return method;
}
private Method findAnnotatedMethod(final Class<?> targetClass) {
final AtomicReference<Method> annotatedMethod = new AtomicReference<Method>();
ReflectionUtils.doWithMethods(targetClass, new ReflectionUtils.MethodCallback() {
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
Annotation annotation = AnnotationUtils.findAnnotation(method, Aggregator.class);
if (annotation != null) {
Assert.isNull(annotatedMethod.get(), "found more than one method on target class ["
+ targetClass + "] with the annotation type [" + Aggregator.class.getName() + "]");
annotatedMethod.set(method);
}
}
});
return annotatedMethod.get();
}
private Method findSinglePublicMethod(Class<?> targetClass) {
Method result = null;
for (Method method : targetClass.getMethods()) {
if (!method.getDeclaringClass().equals(Object.class)) {
if (result != null) {
throw new IllegalArgumentException(
"Class [" + targetClass + "] contains more than one public Method.");
}
result = method;
}
}
return result;
}
}

View File

@@ -1,106 +0,0 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.util;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
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;
import org.springframework.util.ReflectionUtils;
/**
* MethodResolver implementation that finds a <em>single</em> Method on the
* given Class that contains the specified annotation type.
*
* @author Mark Fisher
*/
public class AnnotationMethodResolver implements MethodResolver {
private Class<? extends Annotation> annotationType;
/**
* Create a MethodResolver for the specified Method-level annotation type
*/
public AnnotationMethodResolver(Class<? extends Annotation> annotationType) {
Assert.notNull(annotationType, "annotationType must not be null");
Assert.isTrue(ObjectUtils.containsElement(
annotationType.getAnnotation(Target.class).value(), ElementType.METHOD),
"Annotation [" + annotationType + "] is not a Method-level annotation.");
this.annotationType = annotationType;
}
/**
* 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.
*
* @param clazz the Class instance to check for the annotation
* @param annotationType the Method-level annotation type
*
* @return a single matching Method instance or <code>null</code> if the
* Class contains no Methods with the specified annotation
*
* @throws IllegalArgumentException if more than one Method has the
* 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 {
Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType);
if (annotation != null) {
Assert.isNull(annotatedMethod.get(), "found more than one method on target class ["
+ clazz + "] with the annotation type [" + annotationType + "]");
annotatedMethod.set(method);
}
}
});
return annotatedMethod.get();
}
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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;
/**
* Default MethodResolver implementation. It first checks for a single Method
* with the specified annotation (if not null), and then falls back to a single
* public Method if available.
*
* @author Mark Fisher
*/
public class DefaultMethodResolver implements MethodResolver {
private final AnnotationMethodResolver annotationMethodResolver;
public DefaultMethodResolver() {
this(null);
}
public DefaultMethodResolver(Class<? extends Annotation> annotationType) {
this.annotationMethodResolver = (annotationType != null) ?
new AnnotationMethodResolver(annotationType) : null;
}
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) {
if (this.annotationMethodResolver != null) {
Method method = this.annotationMethodResolver.findMethod(clazz);
if (method != null) {
return method;
}
}
return this.findSinglePublicMethod(clazz);
}
private Method findSinglePublicMethod(Class<?> clazz) {
Method result = null;
for (Method method : clazz.getMethods()) {
if (!method.getDeclaringClass().equals(Object.class)) {
if (result != null) {
throw new IllegalArgumentException(
"Class [" + clazz + "] contains more than one public Method.");
}
result = method;
}
}
return result;
}
}

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.util;
import java.lang.reflect.Method;
/**
* Strategy interface for detecting a single Method on a Class.
*
* @author Mark Fisher
*/
public interface MethodResolver {
/**
* Find a single Method on the provided Object that matches this resolver's
* criteria.
*
* @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.
*
* @throws IllegalArgumentException if more than one Method defined on the
* given Class matches this resolver's criteria
*/
Method findMethod(Class<?> clazz);
}