Example usage for org.springframework.util ReflectionUtils doWithMethods

List of usage examples for org.springframework.util ReflectionUtils doWithMethods

Introduction

In this page you can find the example usage for org.springframework.util ReflectionUtils doWithMethods.

Prototype

public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) 

Source Link

Document

Perform the given callback operation on all matching methods of the given class and superclasses (or given interface and super-interfaces).

Usage

From source file:org.springframework.amqp.rabbit.annotation.RabbitListenerAnnotationBeanPostProcessor.java

@Override
public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
    Class<?> targetClass = AopUtils.getTargetClass(bean);
    Collection<RabbitListener> classLevelListeners = findListenerAnnotations(targetClass);
    final boolean hasClassLevelListeners = classLevelListeners.size() > 0;
    final List<Method> multiMethods = new ArrayList<Method>();
    ReflectionUtils.doWithMethods(targetClass, method -> {
        for (RabbitListener rabbitListener : findListenerAnnotations(method)) {
            processAmqpListener(rabbitListener, method, bean, beanName);
        }/*from  ww  w . j a v  a 2  s .c o m*/
        if (hasClassLevelListeners) {
            RabbitHandler rabbitHandler = AnnotationUtils.findAnnotation(method, RabbitHandler.class);
            if (rabbitHandler != null) {
                multiMethods.add(method);
            }
        }
    }, ReflectionUtils.USER_DECLARED_METHODS);
    if (hasClassLevelListeners) {
        processMultiMethodListeners(classLevelListeners, multiMethods, bean, beanName);
    }
    return bean;
}

From source file:org.springframework.amqp.rabbit.core.BatchingRabbitTemplateTests.java

private int getStreamLevel(Object stream) throws Exception {
    final AtomicReference<Method> m = new AtomicReference<Method>();
    ReflectionUtils.doWithMethods(AbstractCompressingPostProcessor.class, method -> {
        method.setAccessible(true);//  w  w  w .  j  a  v  a2 s  .c om
        m.set(method);
    }, method -> method.getName().equals("getCompressorStream"));
    Object zipStream = m.get().invoke(stream, mock(OutputStream.class));
    return TestUtils.getPropertyValue(zipStream, "def.level", Integer.class);
}

From source file:org.springframework.boot.test.web.client.TestRestTemplateTests.java

@Test
public void restOperationsAreAvailable() throws Exception {
    RestTemplate delegate = mock(RestTemplate.class);
    given(delegate.getUriTemplateHandler()).willReturn(new DefaultUriBuilderFactory());
    final TestRestTemplate restTemplate = new TestRestTemplate(delegate);
    ReflectionUtils.doWithMethods(RestOperations.class, new MethodCallback() {

        @Override/*w w  w . j  av a  2 s.  com*/
        public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
            Method equivalent = ReflectionUtils.findMethod(TestRestTemplate.class, method.getName(),
                    method.getParameterTypes());
            assertThat(equivalent).as("Method %s not found", method).isNotNull();
            assertThat(Modifier.isPublic(equivalent.getModifiers()))
                    .as("Method %s should have been public", equivalent).isTrue();
            try {
                equivalent.invoke(restTemplate, mockArguments(method.getParameterTypes()));
            } catch (Exception ex) {
                throw new IllegalStateException(ex);
            }
        }

        private Object[] mockArguments(Class<?>[] parameterTypes) throws Exception {
            Object[] arguments = new Object[parameterTypes.length];
            for (int i = 0; i < parameterTypes.length; i++) {
                arguments[i] = mockArgument(parameterTypes[i]);
            }
            return arguments;
        }

        @SuppressWarnings("rawtypes")
        private Object mockArgument(Class<?> type) throws Exception {
            if (String.class.equals(type)) {
                return "String";
            }
            if (Object[].class.equals(type)) {
                return new Object[0];
            }
            if (URI.class.equals(type)) {
                return new URI("http://localhost");
            }
            if (HttpMethod.class.equals(type)) {
                return HttpMethod.GET;
            }
            if (Class.class.equals(type)) {
                return Object.class;
            }
            if (RequestEntity.class.equals(type)) {
                return new RequestEntity(HttpMethod.GET, new URI("http://localhost"));
            }
            return mock(type);
        }

    }, (method) -> Modifier.isPublic(method.getModifiers()));

}

From source file:org.springframework.cloud.stream.reactive.StreamEmitterAnnotationBeanPostProcessor.java

@Override
public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
    Class<?> targetClass = AopUtils.getTargetClass(bean);
    ReflectionUtils.doWithMethods(targetClass, method -> {
        if (AnnotatedElementUtils.isAnnotated(method, StreamEmitter.class)) {
            mappedStreamEmitterMethods.add(bean, method);
        }//from w w  w .java  2  s .co m
    }, ReflectionUtils.USER_DECLARED_METHODS);
    return bean;
}

From source file:org.springframework.integration.handler.LambdaMessageProcessor.java

public LambdaMessageProcessor(Object target, Class<?> payloadType) {
    Assert.notNull(target, "'target' must not be null");
    this.target = target;
    final AtomicReference<Method> methodValue = new AtomicReference<>();
    ReflectionUtils.doWithMethods(target.getClass(), methodValue::set, methodCandidate -> {
        boolean isCandidate = !methodCandidate.isBridge() && !methodCandidate.isDefault()
                && methodCandidate.getDeclaringClass() != Object.class
                && Modifier.isPublic(methodCandidate.getModifiers())
                && !Modifier.isStatic(methodCandidate.getModifiers());
        if (isCandidate) {
            Assert.isNull(methodValue.get(), "LambdaMessageProcessor is applicable for inline or lambda "
                    + "classes with single method - functional interface implementations.");
        }/*w w  w.ja  va 2 s .  co m*/
        return isCandidate;
    });

    Assert.notNull(methodValue.get(), "LambdaMessageProcessor is applicable for inline or lambda "
            + "classes with single method - functional interface implementations.");

    this.method = methodValue.get();
    this.method.setAccessible(true);
    this.parameterTypes = this.method.getParameterTypes();
    this.payloadType = payloadType;
}

From source file:org.springframework.integration.handler.support.MessagingMethodInvokerHelper.java

private Map<String, Map<Class<?>, HandlerMethod>> findHandlerMethodsForTarget(final Object targetObject,
        final Class<? extends Annotation> annotationType, final String methodNameToUse,
        final boolean requiresReply) {

    Map<String, Map<Class<?>, HandlerMethod>> handlerMethods = new HashMap<>();

    final Map<Class<?>, HandlerMethod> candidateMethods = new HashMap<>();
    final Map<Class<?>, HandlerMethod> candidateMessageMethods = new HashMap<>();
    final Map<Class<?>, HandlerMethod> fallbackMethods = new HashMap<>();
    final Map<Class<?>, HandlerMethod> fallbackMessageMethods = new HashMap<>();
    final AtomicReference<Class<?>> ambiguousFallbackType = new AtomicReference<>();
    final AtomicReference<Class<?>> ambiguousFallbackMessageGenericType = new AtomicReference<>();
    final Class<?> targetClass = getTargetClass(targetObject);

    final String methodName;

    if (methodNameToUse == null) {
        if (Function.class.isAssignableFrom(targetClass)) {
            methodName = "apply";
        } else if (Consumer.class.isAssignableFrom(targetClass)) {
            methodName = "accept";
        } else {// w ww  .jav  a2 s  . c o m
            methodName = null;
        }
    } else {
        methodName = methodNameToUse;
    }

    MethodFilter methodFilter = new UniqueMethodFilter(targetClass);
    ReflectionUtils.doWithMethods(targetClass, method1 -> {
        boolean matchesAnnotation = false;
        if (method1.isBridge()) {
            return;
        }
        if (isMethodDefinedOnObjectClass(method1)) {
            return;
        }
        if (method1.getDeclaringClass().equals(Proxy.class)) {
            return;
        }
        if (annotationType != null && AnnotationUtils.findAnnotation(method1, annotationType) != null) {
            matchesAnnotation = true;
        } else if (!Modifier.isPublic(method1.getModifiers())) {
            return;
        }
        if (requiresReply && void.class.equals(method1.getReturnType())) {
            return;
        }
        if (methodName != null && !methodName.equals(method1.getName())) {
            return;
        }
        if (methodName == null && ObjectUtils.containsElement(new String[] { "start", "stop", "isRunning" },
                method1.getName())) {
            return;
        }
        HandlerMethod handlerMethod1;
        try {
            method1 = AopUtils.selectInvocableMethod(method1,
                    org.springframework.util.ClassUtils.getUserClass(targetObject));
            InvocableHandlerMethod invocableHandlerMethod = this.messageHandlerMethodFactory
                    .createInvocableHandlerMethod(targetObject, method1);
            handlerMethod1 = new HandlerMethod(invocableHandlerMethod, this.canProcessMessageList);
            checkSpelInvokerRequired(targetClass, method1, handlerMethod1);
        } catch (IneligibleMethodException e) {
            if (logger.isDebugEnabled()) {
                logger.debug("Method [" + method1 + "] is not eligible for Message handling " + e.getMessage()
                        + ".");
            }
            return;
        } catch (Exception e) {
            if (logger.isDebugEnabled()) {
                logger.debug("Method [" + method1 + "] is not eligible for Message handling.", e);
            }
            return;
        }
        if (AnnotationUtils.getAnnotation(method1, Default.class) != null) {
            Assert.state(this.defaultHandlerMethod == null,
                    () -> "Only one method can be @Default, but there are more for: " + targetObject);
            this.defaultHandlerMethod = handlerMethod1;
        }
        Class<?> targetParameterType = handlerMethod1.getTargetParameterType();
        if (matchesAnnotation || annotationType == null) {
            if (handlerMethod1.isMessageMethod()) {
                if (candidateMessageMethods.containsKey(targetParameterType)) {
                    throw new IllegalArgumentException("Found more than one method match for type "
                            + "[Message<" + targetParameterType + ">]");
                }
                candidateMessageMethods.put(targetParameterType, handlerMethod1);
            } else {
                if (candidateMethods.containsKey(targetParameterType)) {
                    String exceptionMessage = "Found more than one method match for ";
                    if (Void.class.equals(targetParameterType)) {
                        exceptionMessage += "empty parameter for 'payload'";
                    } else {
                        exceptionMessage += "type [" + targetParameterType + "]";
                    }
                    throw new IllegalArgumentException(exceptionMessage);
                }
                candidateMethods.put(targetParameterType, handlerMethod1);
            }
        } else {
            if (handlerMethod1.isMessageMethod()) {
                if (fallbackMessageMethods.containsKey(targetParameterType)) {
                    // we need to check for duplicate type matches,
                    // but only if we end up falling back
                    // and we'll only keep track of the first one
                    ambiguousFallbackMessageGenericType.compareAndSet(null, targetParameterType);
                }
                fallbackMessageMethods.put(targetParameterType, handlerMethod1);
            } else {
                if (fallbackMethods.containsKey(targetParameterType)) {
                    // we need to check for duplicate type matches,
                    // but only if we end up falling back
                    // and we'll only keep track of the first one
                    ambiguousFallbackType.compareAndSet(null, targetParameterType);
                }
                fallbackMethods.put(targetParameterType, handlerMethod1);
            }
        }
    }, methodFilter);

    if (candidateMethods.isEmpty() && candidateMessageMethods.isEmpty() && fallbackMethods.isEmpty()
            && fallbackMessageMethods.isEmpty()) {
        findSingleSpecifMethodOnInterfacesIfProxy(targetObject, methodName, candidateMessageMethods,
                candidateMethods);
    }

    if (!candidateMethods.isEmpty() || !candidateMessageMethods.isEmpty()) {
        handlerMethods.put(CANDIDATE_METHODS, candidateMethods);
        handlerMethods.put(CANDIDATE_MESSAGE_METHODS, candidateMessageMethods);
        return handlerMethods;
    }
    if ((ambiguousFallbackType.get() != null || ambiguousFallbackMessageGenericType.get() != null)
            && ServiceActivator.class.equals(annotationType)) {
        /*
         * When there are ambiguous fallback methods,
         * a Service Activator can finally fallback to RequestReplyExchanger.exchange(m).
         * Ambiguous means > 1 method that takes the same payload type, or > 1 method
         * that takes a Message with the same generic type.
         */
        List<Method> frameworkMethods = new ArrayList<>();
        Class<?>[] allInterfaces = org.springframework.util.ClassUtils.getAllInterfacesForClass(targetClass);
        for (Class<?> iface : allInterfaces) {
            try {
                if ("org.springframework.integration.gateway.RequestReplyExchanger".equals(iface.getName())) {
                    frameworkMethods.add(targetClass.getMethod("exchange", Message.class));
                    if (logger.isDebugEnabled()) {
                        logger.debug(targetObject.getClass()
                                + ": Ambiguous fallback methods; using RequestReplyExchanger.exchange()");
                    }
                }
            } catch (Exception e) {
                // should never happen (but would fall through to errors below)
            }
        }
        if (frameworkMethods.size() == 1) {
            Method method = org.springframework.util.ClassUtils.getMostSpecificMethod(frameworkMethods.get(0),
                    targetObject.getClass());
            InvocableHandlerMethod invocableHandlerMethod = this.messageHandlerMethodFactory
                    .createInvocableHandlerMethod(targetObject, method);
            HandlerMethod handlerMethod = new HandlerMethod(invocableHandlerMethod, this.canProcessMessageList);
            checkSpelInvokerRequired(targetClass, method, handlerMethod);
            handlerMethods.put(CANDIDATE_METHODS, Collections.singletonMap(Object.class, handlerMethod));
            handlerMethods.put(CANDIDATE_MESSAGE_METHODS, candidateMessageMethods);
            return handlerMethods;
        }
    }

    Assert.state(!fallbackMethods.isEmpty() || !fallbackMessageMethods.isEmpty(), "Target object of type ["
            + this.targetObject.getClass() + "] has no eligible methods for handling Messages.");

    Assert.isNull(ambiguousFallbackType.get(), "Found ambiguous parameter type [" + ambiguousFallbackType
            + "] for method match: " + fallbackMethods.values());
    Assert.isNull(ambiguousFallbackMessageGenericType.get(), "Found ambiguous parameter type ["
            + ambiguousFallbackMessageGenericType + "] for method match: " + fallbackMethods.values());

    handlerMethods.put(CANDIDATE_METHODS, fallbackMethods);
    handlerMethods.put(CANDIDATE_MESSAGE_METHODS, fallbackMessageMethods);
    return handlerMethods;
}

From source file:org.springframework.integration.handler.support.MessagingMethodInvokerHelper.java

private void findSingleSpecifMethodOnInterfacesIfProxy(final Object targetObject, final String methodName,
        Map<Class<?>, HandlerMethod> candidateMessageMethods, Map<Class<?>, HandlerMethod> candidateMethods) {
    if (AopUtils.isAopProxy(targetObject)) {
        final AtomicReference<Method> targetMethod = new AtomicReference<>();
        final AtomicReference<Class<?>> targetClass = new AtomicReference<>();
        Class<?>[] interfaces = ((Advised) targetObject).getProxiedInterfaces();
        for (Class<?> clazz : interfaces) {
            ReflectionUtils.doWithMethods(clazz, method1 -> {
                if (targetMethod.get() != null) {
                    throw new IllegalStateException("Ambiguous method " + methodName + " on " + targetObject);
                } else {
                    targetMethod.set(method1);
                    targetClass.set(clazz);
                }//  w  ww . ja v  a  2 s . co  m
            }, method12 -> method12.getName().equals(methodName));
        }
        Method theMethod = targetMethod.get();
        if (theMethod != null) {
            theMethod = org.springframework.util.ClassUtils.getMostSpecificMethod(theMethod,
                    targetObject.getClass());
            InvocableHandlerMethod invocableHandlerMethod = this.messageHandlerMethodFactory
                    .createInvocableHandlerMethod(targetObject, theMethod);
            HandlerMethod handlerMethod = new HandlerMethod(invocableHandlerMethod, this.canProcessMessageList);
            checkSpelInvokerRequired(targetClass.get(), theMethod, handlerMethod);
            Class<?> targetParameterType = handlerMethod.getTargetParameterType();
            if (handlerMethod.isMessageMethod()) {
                if (candidateMessageMethods.containsKey(targetParameterType)) {
                    throw new IllegalArgumentException("Found more than one method match for type "
                            + "[Message<" + targetParameterType + ">]");
                }
                candidateMessageMethods.put(targetParameterType, handlerMethod);
            } else {
                if (candidateMethods.containsKey(targetParameterType)) {
                    String exceptionMessage = "Found more than one method match for ";
                    if (Void.class.equals(targetParameterType)) {
                        exceptionMessage += "empty parameter for 'payload'";
                    } else {
                        exceptionMessage += "type [" + targetParameterType + "]";
                    }
                    throw new IllegalArgumentException(exceptionMessage);
                }
                candidateMethods.put(targetParameterType, handlerMethod);
            }
        }
    }
}

From source file:org.springframework.integration.mqtt.MqttAdapterTests.java

@Test
public void testSubscribeFailure() throws Exception {
    DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
    factory.setCleanSession(false);//from  w  w w .  j ava2 s.  c  o  m
    factory.setConnectionTimeout(23);
    factory.setKeepAliveInterval(45);
    factory.setPassword("pass");
    MemoryPersistence persistence = new MemoryPersistence();
    factory.setPersistence(persistence);
    final SocketFactory socketFactory = mock(SocketFactory.class);
    factory.setSocketFactory(socketFactory);
    final Properties props = new Properties();
    factory.setSslProperties(props);
    factory.setUserName("user");
    Will will = new Will("foo", "bar".getBytes(), 2, true);
    factory.setWill(will);

    factory = spy(factory);
    MqttAsyncClient aClient = mock(MqttAsyncClient.class);
    final MqttClient client = mock(MqttClient.class);
    willAnswer(invocation -> client).given(factory).getClientInstance(anyString(), anyString());
    given(client.isConnected()).willReturn(true);
    new DirectFieldAccessor(client).setPropertyValue("aClient", aClient);
    willAnswer(new CallsRealMethods()).given(client).connect(any(MqttConnectOptions.class));
    willAnswer(new CallsRealMethods()).given(client).subscribe(any(String[].class), any(int[].class));
    willReturn(alwaysComplete).given(aClient).connect(any(MqttConnectOptions.class), any(), any());

    IMqttToken token = mock(IMqttToken.class);
    given(token.getGrantedQos()).willReturn(new int[] { 0x80 });
    willReturn(token).given(aClient).subscribe(any(String[].class), any(int[].class), any(), any());

    MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter("foo", "bar", factory,
            "baz", "fix");
    AtomicReference<Method> method = new AtomicReference<>();
    ReflectionUtils.doWithMethods(MqttPahoMessageDrivenChannelAdapter.class, m -> {
        m.setAccessible(true);
        method.set(m);
    }, m -> m.getName().equals("connectAndSubscribe"));
    assertNotNull(method.get());
    try {
        method.get().invoke(adapter);
        fail("Expected InvocationTargetException");
    } catch (InvocationTargetException e) {
        assertThat(e.getCause(), instanceOf(MqttException.class));
        assertThat(((MqttException) e.getCause()).getReasonCode(),
                equalTo((int) MqttException.REASON_CODE_SUBSCRIBE_FAILED));
    }
}

From source file:org.springframework.integration.mqtt.MqttAdapterTests.java

@Test
public void testDifferentQos() throws Exception {
    DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
    factory.setCleanSession(false);/*from   w w  w. ja  v  a  2  s  . c  om*/
    factory.setConnectionTimeout(23);
    factory.setKeepAliveInterval(45);
    factory.setPassword("pass");
    MemoryPersistence persistence = new MemoryPersistence();
    factory.setPersistence(persistence);
    final SocketFactory socketFactory = mock(SocketFactory.class);
    factory.setSocketFactory(socketFactory);
    final Properties props = new Properties();
    factory.setSslProperties(props);
    factory.setUserName("user");
    Will will = new Will("foo", "bar".getBytes(), 2, true);
    factory.setWill(will);

    factory = spy(factory);
    MqttAsyncClient aClient = mock(MqttAsyncClient.class);
    final MqttClient client = mock(MqttClient.class);
    willAnswer(invocation -> client).given(factory).getClientInstance(anyString(), anyString());
    given(client.isConnected()).willReturn(true);
    new DirectFieldAccessor(client).setPropertyValue("aClient", aClient);
    willAnswer(new CallsRealMethods()).given(client).connect(any(MqttConnectOptions.class));
    willAnswer(new CallsRealMethods()).given(client).subscribe(any(String[].class), any(int[].class));
    willReturn(alwaysComplete).given(aClient).connect(any(MqttConnectOptions.class), any(), any());

    IMqttToken token = mock(IMqttToken.class);
    given(token.getGrantedQos()).willReturn(new int[] { 2, 0 });
    willReturn(token).given(aClient).subscribe(any(String[].class), any(int[].class), any(), any());

    MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter("foo", "bar", factory,
            "baz", "fix");
    AtomicReference<Method> method = new AtomicReference<>();
    ReflectionUtils.doWithMethods(MqttPahoMessageDrivenChannelAdapter.class, m -> {
        m.setAccessible(true);
        method.set(m);
    }, m -> m.getName().equals("connectAndSubscribe"));
    assertNotNull(method.get());
    Log logger = spy(TestUtils.getPropertyValue(adapter, "logger", Log.class));
    new DirectFieldAccessor(adapter).setPropertyValue("logger", logger);
    given(logger.isWarnEnabled()).willReturn(true);
    method.get().invoke(adapter);
    verify(logger, atLeastOnce()).warn(
            "Granted QOS different to Requested QOS; topics: [baz, fix] requested: [1, 1] granted: [2, 0]");
    verify(client).setTimeToWait(30_000L);
}

From source file:org.springframework.integration.util.MessagingMethodInvokerHelper.java

private Map<Class<?>, HandlerMethod> findHandlerMethodsForTarget(final Object targetObject,
        final Class<? extends Annotation> annotationType, final String methodName,
        final boolean requiresReply) {

    final Map<Class<?>, HandlerMethod> candidateMethods = new HashMap<Class<?>, HandlerMethod>();
    final Map<Class<?>, HandlerMethod> fallbackMethods = new HashMap<Class<?>, HandlerMethod>();
    final AtomicReference<Class<?>> ambiguousFallbackType = new AtomicReference<Class<?>>();
    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;
            if (method.isBridge()) {
                return;
            }//from ww w. j a  va  2  s  .c o  m
            if (isMethodDefinedOnObjectClass(method)) {
                return;
            }
            if (method.getDeclaringClass().equals(Proxy.class)) {
                return;
            }
            if (!Modifier.isPublic(method.getModifiers())) {
                return;
            }
            if (requiresReply && void.class.equals(method.getReturnType())) {
                return;
            }
            if (methodName != null && !methodName.equals(method.getName())) {
                return;
            }
            if (annotationType != null && AnnotationUtils.findAnnotation(method, annotationType) != null) {
                matchesAnnotation = true;
            }
            HandlerMethod handlerMethod = null;
            try {
                handlerMethod = new HandlerMethod(method, canProcessMessageList);
            } catch (Exception e) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Method [" + method + "] is not eligible for Message handling.", e);
                }
                return;
            }
            Class<?> targetParameterType = handlerMethod.getTargetParameterType().getObjectType();
            if (matchesAnnotation || annotationType == null) {
                Assert.isTrue(!candidateMethods.containsKey(targetParameterType),
                        "Found more than one method match for type [" + targetParameterType + "]");
                candidateMethods.put(targetParameterType, handlerMethod);
            } else {
                if (fallbackMethods.containsKey(targetParameterType)) {
                    // we need to check for duplicate type matches,
                    // but only if we end up falling back
                    // and we'll only keep track of the first one
                    ambiguousFallbackType.compareAndSet(null, targetParameterType);
                }
                fallbackMethods.put(targetParameterType, handlerMethod);
            }
        }
    }, methodFilter);
    if (!candidateMethods.isEmpty()) {
        return candidateMethods;
    }
    if ((fallbackMethods.isEmpty() || ambiguousFallbackType.get() != null)
            && ServiceActivator.class.equals(annotationType)) {
        // a Service Activator can fallback to either MessageHandler.handleMessage(m) or RequestReplyExchanger.exchange(m)
        List<Method> frameworkMethods = new ArrayList<Method>();
        Class<?>[] allInterfaces = org.springframework.util.ClassUtils.getAllInterfacesForClass(targetClass);
        for (Class<?> iface : allInterfaces) {
            try {
                if ("org.springframework.integration.gateway.RequestReplyExchanger".equals(iface.getName())) {
                    frameworkMethods.add(targetClass.getMethod("exchange", Message.class));
                } else if ("org.springframework.integration.core.MessageHandler".equals(iface.getName())
                        && !requiresReply) {
                    frameworkMethods.add(targetClass.getMethod("handleMessage", Message.class));
                }
            } catch (Exception e) {
                // should never happen (but would fall through to errors below)
            }
        }
        if (frameworkMethods.size() == 1) {
            HandlerMethod handlerMethod = new HandlerMethod(frameworkMethods.get(0), canProcessMessageList);
            return Collections.<Class<?>, HandlerMethod>singletonMap(Object.class, handlerMethod);
        }
    }
    Assert.notEmpty(fallbackMethods, "Target object of type [" + this.targetObject.getClass()
            + "] has no eligible methods for handling Messages.");
    Assert.isNull(ambiguousFallbackType.get(), "Found ambiguous parameter type [" + ambiguousFallbackType
            + "] for method match: " + fallbackMethods.values());
    return fallbackMethods;
}