/** * The method scans all beans, that contain methods, * annotated as {@link ScheduledBeanMethod} */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { Class<?> targetClass = AopUtils.getTargetClass(bean); Map<Method, Set<ScheduledBeanMethod>> annotatedMethods = MethodIntrospector.selectMethods(targetClass, (MethodIntrospector.MetadataLookup<Set<ScheduledBeanMethod>>) method -> { Set<ScheduledBeanMethod> scheduledMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations( method, ScheduledBeanMethod.class, ScheduledBeanMethods.class); return (!scheduledMethods.isEmpty() ? scheduledMethods : null); }); for (Map.Entry<Method, Set<ScheduledBeanMethod>> entry : annotatedMethods.entrySet()) { scheduleAnnotatedMethods.add(new ScheduledMethodContext(beanName, entry.getKey(), entry.getValue())); } return bean; }
/** * Detect if the given handler has any methods that can handle messages and if * so register it with the extracted mapping information. * @param handler the handler to check, either an instance of a Spring bean name */ protected final void detectHandlerMethods(final Object handler) { Class<?> handlerType = (handler instanceof String ? this.applicationContext.getType((String) handler) : handler.getClass()); final Class<?> userType = ClassUtils.getUserClass(handlerType); Map<Method, T> methods = MethodIntrospector.selectMethods(userType, new MethodIntrospector.MetadataLookup<T>() { @Override public T inspect(Method method) { return getMappingForMethod(method, userType); } }); if (logger.isDebugEnabled()) { logger.debug(methods.size() + " message handler methods found on " + userType + ": " + methods); } for (Map.Entry<Method, T> entry : methods.entrySet()) { registerHandlerMethod(handler, entry.getKey(), entry.getValue()); } }
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()); } }
/** * Look for handler methods in a handler. * @param handler the bean name of a handler or a handler instance */ protected void detectHandlerMethods(final Object handler) { Class<?> handlerType = (handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass()); final Class<?> userType = ClassUtils.getUserClass(handlerType); Map<Method, T> methods = MethodIntrospector.selectMethods(userType, new MethodIntrospector.MetadataLookup<T>() { @Override public T inspect(Method method) { return getMappingForMethod(method, userType); } }); if (logger.isDebugEnabled()) { logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods); } for (Map.Entry<Method, T> entry : methods.entrySet()) { registerHandlerMethod(handler, entry.getKey(), entry.getValue()); } }
private static Map<Class<? extends Throwable>, Method> initExceptionMappings(Class<?> handlerType) { Map<Class<? extends Throwable>, Method> result = new HashMap<Class<? extends Throwable>, Method>(); for (Method method : MethodIntrospector.selectMethods(handlerType, EXCEPTION_HANDLER_METHOD_FILTER)) { for(Class<? extends Throwable> exception : getExceptionsFromMethodSignature(method)) { result.put(exception, method); } } return result; }
/** * A constructor that finds {@link ExceptionHandler} methods in the given type. * @param handlerType the type to introspect */ public ExceptionHandlerMethodResolver(Class<?> handlerType) { for (Method method : MethodIntrospector.selectMethods(handlerType, EXCEPTION_HANDLER_METHODS)) { for (Class<? extends Throwable> exceptionType : detectExceptionMappings(method)) { addExceptionMapping(exceptionType, method); } } }
private void runTest(Object controller) throws Exception { HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite(); resolvers.addResolver(new ModelAttributeMethodProcessor(false)); resolvers.addResolver(new ModelMethodProcessor()); WebDataBinderFactory dataBinderFactory = new DefaultDataBinderFactory(null); Class<?> type = controller.getClass(); Set<Method> methods = MethodIntrospector.selectMethods(type, METHOD_FILTER); List<InvocableHandlerMethod> modelMethods = new ArrayList<InvocableHandlerMethod>(); for (Method method : methods) { InvocableHandlerMethod modelMethod = new InvocableHandlerMethod(controller, method); modelMethod.setHandlerMethodArgumentResolvers(resolvers); modelMethod.setDataBinderFactory(dataBinderFactory); modelMethods.add(modelMethod); } Collections.shuffle(modelMethods); SessionAttributesHandler sessionHandler = new SessionAttributesHandler(type, this.sessionAttributeStore); ModelFactory factory = new ModelFactory(modelMethods, dataBinderFactory, sessionHandler); factory.initModel(this.webRequest, this.mavContainer, new HandlerMethod(controller, "handle")); if (logger.isDebugEnabled()) { StringBuilder sb = new StringBuilder(); for (String name : getInvokedMethods()) { sb.append(" >> ").append(name); } logger.debug(sb); } }
/** * Process the given {@link JmsListener} annotation on the given method, * registering a corresponding endpoint for the given bean instance. * @param jmsListener the annotation to process * @param mostSpecificMethod the annotated method * @param bean the instance to invoke the method on * @see #createMethodJmsListenerEndpoint() * @see JmsListenerEndpointRegistrar#registerEndpoint */ protected void processJmsListener(JmsListener jmsListener, Method mostSpecificMethod, Object bean) { Method invocableMethod = MethodIntrospector.selectInvocableMethod(mostSpecificMethod, bean.getClass()); MethodJmsListenerEndpoint endpoint = createMethodJmsListenerEndpoint(); endpoint.setBean(bean); endpoint.setMethod(invocableMethod); endpoint.setMostSpecificMethod(mostSpecificMethod); endpoint.setMessageHandlerMethodFactory(this.messageHandlerMethodFactory); endpoint.setBeanFactory(this.beanFactory); endpoint.setId(getEndpointId(jmsListener)); endpoint.setDestination(resolve(jmsListener.destination())); if (StringUtils.hasText(jmsListener.selector())) { endpoint.setSelector(resolve(jmsListener.selector())); } if (StringUtils.hasText(jmsListener.subscription())) { endpoint.setSubscription(resolve(jmsListener.subscription())); } if (StringUtils.hasText(jmsListener.concurrency())) { endpoint.setConcurrency(resolve(jmsListener.concurrency())); } JmsListenerContainerFactory<?> factory = null; String containerFactoryBeanName = resolve(jmsListener.containerFactory()); if (StringUtils.hasText(containerFactoryBeanName)) { Assert.state(this.beanFactory != null, "BeanFactory must be set to obtain container factory by bean name"); try { factory = this.beanFactory.getBean(containerFactoryBeanName, JmsListenerContainerFactory.class); } catch (NoSuchBeanDefinitionException ex) { throw new BeanInitializationException("Could not register JMS listener endpoint on [" + mostSpecificMethod + "], no " + JmsListenerContainerFactory.class.getSimpleName() + " with id '" + containerFactoryBeanName + "' was found in the application context", ex); } } this.registrar.registerEndpoint(endpoint, factory); }
private <A extends Annotation> Map<Method, Set<A>> findAnnotatedMethods(Class<?> targetClass, Class<A> single, Class<? extends Annotation> plural) { return MethodIntrospector.selectMethods(targetClass, (MetadataLookup<Set<A>>) method -> { Set<A> matsMappingAnnotations = AnnotationUtils.getRepeatableAnnotations(method, single, plural); return (!matsMappingAnnotations.isEmpty() ? matsMappingAnnotations : null); }); }
public Map<Method, T> getMethods(final Class<?> type, final Class<T> annotationClass){ return MethodIntrospector.selectMethods(type, new MethodIntrospector.MetadataLookup<T>() { @Override public T inspect(Method method) { return AnnotationUtils.findAnnotation(method, annotationClass); } }); }
private void initControllerAdviceCache() { if (getApplicationContext() == null) { return; } if (logger.isInfoEnabled()) { logger.info("Looking for @ControllerAdvice: " + getApplicationContext()); } List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext()); AnnotationAwareOrderComparator.sort(beans); List<Object> requestResponseBodyAdviceBeans = new ArrayList<Object>(); for (ControllerAdviceBean bean : beans) { Set<Method> attrMethods = MethodIntrospector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS); if (!attrMethods.isEmpty()) { this.modelAttributeAdviceCache.put(bean, attrMethods); if (logger.isInfoEnabled()) { logger.info("Detected @ModelAttribute methods in " + bean); } } Set<Method> binderMethods = MethodIntrospector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS); if (!binderMethods.isEmpty()) { this.initBinderAdviceCache.put(bean, binderMethods); if (logger.isInfoEnabled()) { logger.info("Detected @InitBinder methods in " + bean); } } if (RequestBodyAdvice.class.isAssignableFrom(bean.getBeanType())) { requestResponseBodyAdviceBeans.add(bean); if (logger.isInfoEnabled()) { logger.info("Detected RequestBodyAdvice bean in " + bean); } } if (ResponseBodyAdvice.class.isAssignableFrom(bean.getBeanType())) { requestResponseBodyAdviceBeans.add(bean); if (logger.isInfoEnabled()) { logger.info("Detected ResponseBodyAdvice bean in " + bean); } } } if (!requestResponseBodyAdviceBeans.isEmpty()) { this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans); } }
/** * Select an invocable method on the target type: either the given method itself * if actually exposed on the target type, or otherwise a corresponding method * on one of the target type's interfaces or on the target type itself. * @param method the method to check * @param targetType the target type to search methods on (typically an AOP proxy) * @return a corresponding invocable method on the target type * @throws IllegalStateException if the given method is not invocable on the given * target type (typically due to a proxy mismatch) * @since 4.3 * @see MethodIntrospector#selectInvocableMethod(Method, Class) */ public static Method selectInvocableMethod(Method method, Class<?> targetType) { Method methodToUse = MethodIntrospector.selectInvocableMethod(method, targetType); if (Modifier.isPrivate(methodToUse.getModifiers()) && !Modifier.isStatic(methodToUse.getModifiers()) && SpringProxy.class.isAssignableFrom(targetType)) { throw new IllegalStateException(String.format( "Need to invoke method '%s' found on proxy for target class '%s' but cannot " + "be delegated to target bean. Switch its visibility to package or protected.", method.getName(), method.getDeclaringClass().getSimpleName())); } return methodToUse; }
/** * Select handler methods for the given handler type. * <p>Callers define handler methods of interest through the {@link MethodFilter} parameter. * @param handlerType the handler type to search handler methods on * @param handlerMethodFilter a {@link MethodFilter} to help recognize handler methods of interest * @return the selected methods, or an empty set * @see MethodIntrospector#selectMethods(Class, MethodFilter) */ public static Set<Method> selectMethods(Class<?> handlerType, MethodFilter handlerMethodFilter) { return MethodIntrospector.selectMethods(handlerType, handlerMethodFilter); }