List of usage examples for org.springframework.integration.util UniqueMethodFilter UniqueMethodFilter
public UniqueMethodFilter(Class<?> targetClass)
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 {//from ww w . j a v a 2 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.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 w w w. j av a 2 s . com*/ 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; }