Search in sources :

Example 1 with MethodFilter

use of org.springframework.util.ReflectionUtils.MethodFilter in project spring-integration by spring-projects.

the class MessagingMethodInvokerHelper method findHandlerMethodsForTarget.

private Map<String, Map<Class<?>, HandlerMethod>> findHandlerMethodsForTarget(final Object targetObject, final Class<? extends Annotation> annotationType, final String methodName, 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);
    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;
}
Also used : MutableMessage(org.springframework.integration.support.MutableMessage) Message(org.springframework.messaging.Message) HashMap(java.util.HashMap) InvocableHandlerMethod(org.springframework.messaging.handler.invocation.InvocableHandlerMethod) ArrayList(java.util.ArrayList) MethodFilter(org.springframework.util.ReflectionUtils.MethodFilter) AnnotatedMethodFilter(org.springframework.integration.util.AnnotatedMethodFilter) FixedMethodFilter(org.springframework.integration.util.FixedMethodFilter) UniqueMethodFilter(org.springframework.integration.util.UniqueMethodFilter) AtomicReference(java.util.concurrent.atomic.AtomicReference) Method(java.lang.reflect.Method) InvocableHandlerMethod(org.springframework.messaging.handler.invocation.InvocableHandlerMethod) UniqueMethodFilter(org.springframework.integration.util.UniqueMethodFilter) Default(org.springframework.integration.annotation.Default) ServiceActivator(org.springframework.integration.annotation.ServiceActivator) InvocableHandlerMethod(org.springframework.messaging.handler.invocation.InvocableHandlerMethod) ConversionFailedException(org.springframework.core.convert.ConversionFailedException) MessageHandlingException(org.springframework.messaging.MessageHandlingException) EvaluationException(org.springframework.expression.EvaluationException) ConverterNotFoundException(org.springframework.core.convert.ConverterNotFoundException) MessageConversionException(org.springframework.messaging.converter.MessageConversionException) MethodArgumentResolutionException(org.springframework.messaging.handler.invocation.MethodArgumentResolutionException) NoSuchBeanDefinitionException(org.springframework.beans.factory.NoSuchBeanDefinitionException) Map(java.util.Map) HashMap(java.util.HashMap)

Example 2 with MethodFilter

use of org.springframework.util.ReflectionUtils.MethodFilter in project BroadleafCommerce by BroadleafCommerce.

the class FrameworkMvcUriComponentsBuilder method getMethod.

private static Method getMethod(Class<?> controllerType, final String methodName, final Object... args) {
    MethodFilter selector = new MethodFilter() {

        @Override
        public boolean matches(Method method) {
            String name = method.getName();
            int argLength = method.getParameterTypes().length;
            return (name.equals(methodName) && argLength == args.length);
        }
    };
    Set<Method> methods = MethodIntrospector.selectMethods(controllerType, selector);
    if (methods.size() == 1) {
        return methods.iterator().next();
    } else if (methods.size() > 1) {
        throw new IllegalArgumentException(String.format("Found two methods named '%s' accepting arguments %s in controller %s: [%s]", methodName, Arrays.asList(args), controllerType.getName(), methods));
    } else {
        throw new IllegalArgumentException("No method named '" + methodName + "' with " + args.length + " arguments found in controller " + controllerType.getName());
    }
}
Also used : MethodFilter(org.springframework.util.ReflectionUtils.MethodFilter) HandlerMethod(org.springframework.web.method.HandlerMethod) Method(java.lang.reflect.Method)

Example 3 with MethodFilter

use of org.springframework.util.ReflectionUtils.MethodFilter in project spring-framework by spring-projects.

the class MvcUriComponentsBuilder method getMethod.

private static Method getMethod(Class<?> controllerType, final String methodName, final Object... args) {
    MethodFilter selector = method -> {
        String name = method.getName();
        int argLength = method.getParameterCount();
        return (name.equals(methodName) && argLength == args.length);
    };
    Set<Method> methods = MethodIntrospector.selectMethods(controllerType, selector);
    if (methods.size() == 1) {
        return methods.iterator().next();
    } else if (methods.size() > 1) {
        throw new IllegalArgumentException(String.format("Found two methods named '%s' accepting arguments %s in controller %s: [%s]", methodName, Arrays.asList(args), controllerType.getName(), methods));
    } else {
        throw new IllegalArgumentException("No method named '" + methodName + "' with " + args.length + " arguments found in controller " + controllerType.getName());
    }
}
Also used : ParameterNameDiscoverer(org.springframework.core.ParameterNameDiscoverer) AnnotatedElementUtils(org.springframework.core.annotation.AnnotatedElementUtils) Enhancer(org.springframework.cglib.proxy.Enhancer) ObjenesisException(org.springframework.objenesis.ObjenesisException) UriComponentsBuilder(org.springframework.web.util.UriComponentsBuilder) Arrays(java.util.Arrays) HttpServletRequest(jakarta.servlet.http.HttpServletRequest) MethodIntrospector(org.springframework.core.MethodIntrospector) RequestParamMethodArgumentResolver(org.springframework.web.method.annotation.RequestParamMethodArgumentResolver) RequestMapping(org.springframework.web.bind.annotation.RequestMapping) HashMap(java.util.HashMap) RequestContextHolder(org.springframework.web.context.request.RequestContextHolder) HandlerMethod(org.springframework.web.method.HandlerMethod) EmptyTargetSource(org.springframework.aop.target.EmptyTargetSource) RequestMappingInfoHandlerMapping(org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping) DispatcherServlet(org.springframework.web.servlet.DispatcherServlet) Callback(org.springframework.cglib.proxy.Callback) Map(java.util.Map) MethodParameter(org.springframework.core.MethodParameter) CompositeUriComponentsContributor(org.springframework.web.method.support.CompositeUriComponentsContributor) RequestAttributes(org.springframework.web.context.request.RequestAttributes) Nullable(org.springframework.lang.Nullable) AntPathMatcher(org.springframework.util.AntPathMatcher) Method(java.lang.reflect.Method) SpringObjenesis(org.springframework.objenesis.SpringObjenesis) SpringNamingPolicy(org.springframework.cglib.core.SpringNamingPolicy) ServletUriComponentsBuilder(org.springframework.web.servlet.support.ServletUriComponentsBuilder) PathMatcher(org.springframework.util.PathMatcher) ObjectUtils(org.springframework.util.ObjectUtils) Set(java.util.Set) WebApplicationContext(org.springframework.web.context.WebApplicationContext) SynthesizingMethodParameter(org.springframework.core.annotation.SynthesizingMethodParameter) Factory(org.springframework.cglib.proxy.Factory) MethodFilter(org.springframework.util.ReflectionUtils.MethodFilter) ServletRequestAttributes(org.springframework.web.context.request.ServletRequestAttributes) MethodInterceptor(org.aopalliance.intercept.MethodInterceptor) List(java.util.List) MethodProxy(org.springframework.cglib.proxy.MethodProxy) DefaultParameterNameDiscoverer(org.springframework.core.DefaultParameterNameDiscoverer) ReflectionUtils(org.springframework.util.ReflectionUtils) NoSuchBeanDefinitionException(org.springframework.beans.factory.NoSuchBeanDefinitionException) ProxyFactory(org.springframework.aop.framework.ProxyFactory) Log(org.apache.commons.logging.Log) LogFactory(org.apache.commons.logging.LogFactory) Assert(org.springframework.util.Assert) StringUtils(org.springframework.util.StringUtils) MethodFilter(org.springframework.util.ReflectionUtils.MethodFilter) HandlerMethod(org.springframework.web.method.HandlerMethod) Method(java.lang.reflect.Method)

Example 4 with MethodFilter

use of org.springframework.util.ReflectionUtils.MethodFilter in project netty-socketio by mrniko.

the class SpringAnnotationScanner method postProcessBeforeInitialization.

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    final AtomicBoolean add = new AtomicBoolean();
    ReflectionUtils.doWithMethods(bean.getClass(), new MethodCallback() {

        @Override
        public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
            add.set(true);
        }
    }, new MethodFilter() {

        @Override
        public boolean matches(Method method) {
            for (Class<? extends Annotation> annotationClass : annotations) {
                if (method.isAnnotationPresent(annotationClass)) {
                    return true;
                }
            }
            return false;
        }
    });
    if (add.get()) {
        originalBeanClass = bean.getClass();
    }
    return bean;
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) MethodFilter(org.springframework.util.ReflectionUtils.MethodFilter) Method(java.lang.reflect.Method) MethodCallback(org.springframework.util.ReflectionUtils.MethodCallback) Annotation(java.lang.annotation.Annotation)

Example 5 with MethodFilter

use of org.springframework.util.ReflectionUtils.MethodFilter in project spring-framework by spring-projects.

the class BridgeMethodResolver method findBridgedMethod.

/**
 * Find the original method for the supplied {@link Method bridge Method}.
 * <p>It is safe to call this method passing in a non-bridge {@link Method} instance.
 * In such a case, the supplied {@link Method} instance is returned directly to the caller.
 * Callers are <strong>not</strong> required to check for bridging before calling this method.
 * @param bridgeMethod the method to introspect
 * @return the original method (either the bridged method or the passed-in method
 * if no more specific one could be found)
 */
public static Method findBridgedMethod(Method bridgeMethod) {
    if (!bridgeMethod.isBridge()) {
        return bridgeMethod;
    }
    Method bridgedMethod = cache.get(bridgeMethod);
    if (bridgedMethod == null) {
        // Gather all methods with matching name and parameter size.
        List<Method> candidateMethods = new ArrayList<>();
        MethodFilter filter = candidateMethod -> isBridgedCandidateFor(candidateMethod, bridgeMethod);
        ReflectionUtils.doWithMethods(bridgeMethod.getDeclaringClass(), candidateMethods::add, filter);
        if (!candidateMethods.isEmpty()) {
            bridgedMethod = candidateMethods.size() == 1 ? candidateMethods.get(0) : searchCandidates(candidateMethods, bridgeMethod);
        }
        if (bridgedMethod == null) {
            // A bridge method was passed in but we couldn't find the bridged method.
            // Let's proceed with the passed-in method and hope for the best...
            bridgedMethod = bridgeMethod;
        }
        cache.put(bridgeMethod, bridgedMethod);
    }
    return bridgedMethod;
}
Also used : ConcurrentReferenceHashMap(org.springframework.util.ConcurrentReferenceHashMap) Arrays(java.util.Arrays) List(java.util.List) ClassUtils(org.springframework.util.ClassUtils) Type(java.lang.reflect.Type) ReflectionUtils(org.springframework.util.ReflectionUtils) Map(java.util.Map) Nullable(org.springframework.lang.Nullable) MethodFilter(org.springframework.util.ReflectionUtils.MethodFilter) Method(java.lang.reflect.Method) ArrayList(java.util.ArrayList) MethodFilter(org.springframework.util.ReflectionUtils.MethodFilter) ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method)

Aggregations

Method (java.lang.reflect.Method)7 MethodFilter (org.springframework.util.ReflectionUtils.MethodFilter)7 ArrayList (java.util.ArrayList)3 List (java.util.List)3 Map (java.util.Map)3 Arrays (java.util.Arrays)2 HashMap (java.util.HashMap)2 NoSuchBeanDefinitionException (org.springframework.beans.factory.NoSuchBeanDefinitionException)2 Nullable (org.springframework.lang.Nullable)2 ReflectionUtils (org.springframework.util.ReflectionUtils)2 HandlerMethod (org.springframework.web.method.HandlerMethod)2 HttpServletRequest (jakarta.servlet.http.HttpServletRequest)1 Annotation (java.lang.annotation.Annotation)1 Field (java.lang.reflect.Field)1 Modifier (java.lang.reflect.Modifier)1 Type (java.lang.reflect.Type)1 ConnectException (java.rmi.ConnectException)1 RemoteException (java.rmi.RemoteException)1 Set (java.util.Set)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1