diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java index 87b23d6592..3c0b63bc32 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -30,26 +30,30 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Encapsulates information about a bean method consisting of a {@link #getMethod() method} - * and a {@link #getBean() bean}. Provides convenient access to method parameters, - * method return value, method annotations. + * Encapsulates information about a handler method consisting of a + * {@linkplain #getMethod() method} and a {@linkplain #getBean() bean}. + * Provides convenient access to method parameters, method return value, method annotations. * - *

The class may be created with a bean instance or with a bean name (e.g. lazy bean, - * prototype bean). Use {@link #createWithResolvedBean()} to obtain an {@link HandlerMethod} - * instance with a bean instance initialized through the bean factory. + *

The class may be created with a bean instance or with a bean name (e.g. lazy-init bean, + * prototype bean). Use {@link #createWithResolvedBean()} to obtain a {@link HandlerMethod} + * instance with a bean instance resolved through the associated {@link BeanFactory}. * * @author Arjen Poutsma * @author Rossen Stoyanchev + * @author Juergen Hoeller * @since 4.0 */ public class HandlerMethod { - protected final Log logger = LogFactory.getLog(HandlerMethod.class); + /** Logger that is available to subclasses */ + protected final Log logger = LogFactory.getLog(getClass()); private final Object bean; private final BeanFactory beanFactory; + private final Class beanType; + private final Method method; private final Method bridgedMethod; @@ -65,6 +69,7 @@ public class HandlerMethod { Assert.notNull(method, "Method is required"); this.bean = bean; this.beanFactory = null; + this.beanType = ClassUtils.getUserClass(bean); this.method = method; this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); this.parameters = initMethodParameters(); @@ -79,6 +84,7 @@ public class HandlerMethod { Assert.notNull(methodName, "Method name is required"); this.bean = bean; this.beanFactory = null; + this.beanType = ClassUtils.getUserClass(bean); this.method = bean.getClass().getMethod(methodName, parameterTypes); this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(this.method); this.parameters = initMethodParameters(); @@ -93,22 +99,22 @@ public class HandlerMethod { Assert.hasText(beanName, "Bean name is required"); Assert.notNull(beanFactory, "BeanFactory is required"); Assert.notNull(method, "Method is required"); - Assert.isTrue(beanFactory.containsBean(beanName), - "BeanFactory [" + beanFactory + "] does not contain bean [" + beanName + "]"); this.bean = beanName; this.beanFactory = beanFactory; + this.beanType = ClassUtils.getUserClass(beanFactory.getType(beanName)); this.method = method; this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); this.parameters = initMethodParameters(); } /** - * Copy constructor for use in sub-classes. + * Copy constructor for use in subclasses. */ protected HandlerMethod(HandlerMethod handlerMethod) { Assert.notNull(handlerMethod, "HandlerMethod is required"); this.bean = handlerMethod.bean; this.beanFactory = handlerMethod.beanFactory; + this.beanType = handlerMethod.beanType; this.method = handlerMethod.method; this.bridgedMethod = handlerMethod.bridgedMethod; this.parameters = handlerMethod.parameters; @@ -122,6 +128,7 @@ public class HandlerMethod { Assert.notNull(handler, "Handler object is required"); this.bean = handler; this.beanFactory = handlerMethod.beanFactory; + this.beanType = handlerMethod.beanType; this.method = handlerMethod.method; this.bridgedMethod = handlerMethod.bridgedMethod; this.parameters = handlerMethod.parameters; @@ -152,18 +159,17 @@ public class HandlerMethod { } /** - * Returns the type of the handler for this handler method. - * Note that if the bean type is a CGLIB-generated class, the original, user-defined class is returned. + * This method returns the type of the handler for this handler method. + *

Note that if the bean type is a CGLIB-generated class, the original + * user-defined class is returned. */ public Class getBeanType() { - Class clazz = (this.bean instanceof String ? - this.beanFactory.getType((String) this.bean) : this.bean.getClass()); - return ClassUtils.getUserClass(clazz); + return this.beanType; } /** - * If the bean method is a bridge method, this method returns the bridged (user-defined) method. - * Otherwise it returns the same method as {@link #getMethod()}. + * If the bean method is a bridge method, this method returns the bridged + * (user-defined) method. Otherwise it returns the same method as {@link #getMethod()}. */ protected Method getBridgedMethod() { return this.bridgedMethod; @@ -198,8 +204,8 @@ public class HandlerMethod { } /** - * Returns a single annotation on the underlying method traversing its super methods if no - * annotation can be found on the given method itself. + * Returns a single annotation on the underlying method traversing its super methods + * if no annotation can be found on the given method itself. * @param annotationType the type of annotation to introspect the method for. * @return the annotation, or {@code null} if none found */ @@ -208,8 +214,8 @@ public class HandlerMethod { } /** - * If the provided instance contains a bean name rather than an object instance, the bean name is resolved - * before a {@link HandlerMethod} is created and returned. + * If the provided instance contains a bean name rather than an object instance, + * the bean name is resolved before a {@link HandlerMethod} is created and returned. */ public HandlerMethod createWithResolvedBean() { Object handler = this.bean; @@ -220,26 +226,27 @@ public class HandlerMethod { return new HandlerMethod(this, handler); } + public String getShortLogMessage() { + int args = this.method.getParameterTypes().length; + return getBeanType().getName() + "#" + this.method.getName() + "[" + args + " args]"; + } + + @Override - public boolean equals(Object obj) { - if (this == obj) { + public boolean equals(Object other) { + if (this == other) { return true; } - if (obj != null && obj instanceof HandlerMethod) { - HandlerMethod other = (HandlerMethod) obj; - return this.bean.equals(other.bean) && this.method.equals(other.method); + if (!(other instanceof HandlerMethod)) { + return false; } - return false; + HandlerMethod otherMethod = (HandlerMethod) other; + return (this.bean.equals(otherMethod.bean) && this.method.equals(otherMethod.method)); } @Override public int hashCode() { - return this.bean.hashCode() * 31 + this.method.hashCode(); - } - - public String getShortLogMessage() { - int args = method.getParameterTypes().length; - return getBeanType().getName() + "#" + this.method.getName() + "[" + args + " args]"; + return (this.bean.hashCode() * 31 + this.method.hashCode()); } @Override diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java index e14f0b07e7..18a119669c 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java @@ -30,7 +30,6 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -159,7 +158,7 @@ public abstract class AbstractMethodMessageHandler /** * Configure the complete list of supported argument types effectively overriding * the ones configured by default. This is an advanced option. For most use cases - * it should be sufficient to use {@link #setCustomArgumentResolvers(java.util.List)}. + * it should be sufficient to use {@link #setCustomArgumentResolvers}. */ public void setArgumentResolvers(List argumentResolvers) { if (argumentResolvers == null) { @@ -176,7 +175,7 @@ public abstract class AbstractMethodMessageHandler /** * Configure the complete list of supported return value types effectively overriding * the ones configured by default. This is an advanced option. For most use cases - * it should be sufficient to use {@link #setCustomReturnValueHandlers(java.util.List)} + * it should be sufficient to use {@link #setCustomReturnValueHandlers}. */ public void setReturnValueHandlers(List returnValueHandlers) { if (returnValueHandlers == null) { @@ -198,7 +197,7 @@ public abstract class AbstractMethodMessageHandler } @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @@ -209,7 +208,6 @@ public abstract class AbstractMethodMessageHandler @Override public void afterPropertiesSet() { - if (this.argumentResolvers.getResolvers().isEmpty()) { this.argumentResolvers.addResolvers(initArgumentResolvers()); } @@ -227,17 +225,17 @@ public abstract class AbstractMethodMessageHandler /** * Return the list of argument resolvers to use. Invoked only if the resolvers - * have not already been set via {@link #setArgumentResolvers(java.util.List)}. - *

Sub-classes should also take into account custom argument types configured via - * {@link #setCustomArgumentResolvers(java.util.List)}. + * have not already been set via {@link #setArgumentResolvers}. + *

Subclasses should also take into account custom argument types configured via + * {@link #setCustomArgumentResolvers}. */ protected abstract List initArgumentResolvers(); /** * Return the list of return value handlers to use. Invoked only if the return - * value handlers have not already been set via {@link #setReturnValueHandlers(java.util.List)}. - *

Sub-classes should also take into account custom return value types configured - * via {@link #setCustomReturnValueHandlers(java.util.List)}. + * value handlers have not already been set via {@link #setReturnValueHandlers}. + *

Subclasses should also take into account custom return value types configured + * via {@link #setCustomReturnValueHandlers}. */ protected abstract List initReturnValueHandlers(); @@ -253,9 +251,8 @@ public abstract class AbstractMethodMessageHandler * @param handler the handler to check, either an instance of a Spring bean name */ protected final void detectHandlerMethods(Object handler) { - - Class handlerType = (handler instanceof String) ? - this.applicationContext.getType((String) handler) : handler.getClass(); + Class handlerType = (handler instanceof String ? + this.applicationContext.getType((String) handler) : handler.getClass()); final Class userType = ClassUtils.getUserClass(handlerType); @@ -290,14 +287,13 @@ public abstract class AbstractMethodMessageHandler * under the same mapping */ protected void registerHandlerMethod(Object handler, Method method, T mapping) { - HandlerMethod newHandlerMethod = createHandlerMethod(handler, method); - HandlerMethod oldHandlerMethod = handlerMethods.get(mapping); + HandlerMethod oldHandlerMethod = this.handlerMethods.get(mapping); if (oldHandlerMethod != null && !oldHandlerMethod.equals(newHandlerMethod)) { - throw new IllegalStateException("Ambiguous mapping found. Cannot map '" + newHandlerMethod.getBean() - + "' bean method \n" + newHandlerMethod + "\nto " + mapping + ": There is already '" - + oldHandlerMethod.getBean() + "' bean method\n" + oldHandlerMethod + " mapped."); + throw new IllegalStateException("Ambiguous mapping found. Cannot map '" + newHandlerMethod.getBean() + + "' bean method \n" + newHandlerMethod + "\nto " + mapping + ": There is already '" + + oldHandlerMethod.getBean() + "' bean method\n" + oldHandlerMethod + " mapped."); } this.handlerMethods.put(mapping, newHandlerMethod); @@ -318,7 +314,8 @@ public abstract class AbstractMethodMessageHandler HandlerMethod handlerMethod; if (handler instanceof String) { String beanName = (String) handler; - handlerMethod = new HandlerMethod(beanName, this.applicationContext, method); + handlerMethod = new HandlerMethod(beanName, + this.applicationContext.getAutowireCapableBeanFactory(), method); } else { handlerMethod = new HandlerMethod(handler, method); @@ -333,7 +330,7 @@ public abstract class AbstractMethodMessageHandler protected abstract Set getDirectLookupDestinations(T mapping); /** - * Sub-classes can invoke this method to populate the MessagingAdviceBean cache + * Subclasses can invoke this method to populate the MessagingAdviceBean cache * (e.g. to support "global" {@code @MessageExceptionHandler}). * @since 4.2 */ @@ -505,9 +502,8 @@ public abstract class AbstractMethodMessageHandler } this.returnValueHandlers.handleReturnValue(returnValue, returnType, message); } - catch (Throwable t) { - logger.error("Error while handling exception", t); - return; + catch (Throwable ex2) { + logger.error("Error while processing handler method exception", ex2); } } diff --git a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java index a0a5063ce2..cdbf7315a5 100644 --- a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java +++ b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -30,9 +30,9 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Encapsulates information about a handler method consisting of a {@linkplain #getMethod() method} - * and a {@linkplain #getBean() bean}. Provides convenient access to method parameters, - * method return value, method annotations. + * Encapsulates information about a handler method consisting of a + * {@linkplain #getMethod() method} and a {@linkplain #getBean() bean}. + * Provides convenient access to method parameters, method return value, method annotations. * *

The class may be created with a bean instance or with a bean name (e.g. lazy-init bean, * prototype bean). Use {@link #createWithResolvedBean()} to obtain a {@link HandlerMethod} @@ -40,17 +40,20 @@ import org.springframework.util.ClassUtils; * * @author Arjen Poutsma * @author Rossen Stoyanchev + * @author Juergen Hoeller * @since 3.1 */ public class HandlerMethod { /** Logger that is available to subclasses */ - protected final Log logger = LogFactory.getLog(HandlerMethod.class); + protected final Log logger = LogFactory.getLog(getClass()); private final Object bean; private final BeanFactory beanFactory; + private final Class beanType; + private final Method method; private final Method bridgedMethod; @@ -66,6 +69,7 @@ public class HandlerMethod { Assert.notNull(method, "Method is required"); this.bean = bean; this.beanFactory = null; + this.beanType = ClassUtils.getUserClass(bean); this.method = method; this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); this.parameters = initMethodParameters(); @@ -80,6 +84,7 @@ public class HandlerMethod { Assert.notNull(methodName, "Method name is required"); this.bean = bean; this.beanFactory = null; + this.beanType = ClassUtils.getUserClass(bean); this.method = bean.getClass().getMethod(methodName, parameterTypes); this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(this.method); this.parameters = initMethodParameters(); @@ -94,22 +99,22 @@ public class HandlerMethod { Assert.hasText(beanName, "Bean name is required"); Assert.notNull(beanFactory, "BeanFactory is required"); Assert.notNull(method, "Method is required"); - Assert.isTrue(beanFactory.containsBean(beanName), - "BeanFactory [" + beanFactory + "] does not contain bean [" + beanName + "]"); this.bean = beanName; this.beanFactory = beanFactory; + this.beanType = ClassUtils.getUserClass(beanFactory.getType(beanName)); this.method = method; this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); this.parameters = initMethodParameters(); } /** - * Copy constructor for use in sub-classes. + * Copy constructor for use in subclasses. */ protected HandlerMethod(HandlerMethod handlerMethod) { Assert.notNull(handlerMethod, "HandlerMethod is required"); this.bean = handlerMethod.bean; this.beanFactory = handlerMethod.beanFactory; + this.beanType = handlerMethod.beanType; this.method = handlerMethod.method; this.bridgedMethod = handlerMethod.bridgedMethod; this.parameters = handlerMethod.parameters; @@ -123,6 +128,7 @@ public class HandlerMethod { Assert.notNull(handler, "Handler object is required"); this.bean = handler; this.beanFactory = handlerMethod.beanFactory; + this.beanType = handlerMethod.beanType; this.method = handlerMethod.method; this.bridgedMethod = handlerMethod.bridgedMethod; this.parameters = handlerMethod.parameters; @@ -153,18 +159,17 @@ public class HandlerMethod { } /** - * Returns the type of the handler for this handler method. - * Note that if the bean type is a CGLIB-generated class, the original, user-defined class is returned. + * This method returns the type of the handler for this handler method. + *

Note that if the bean type is a CGLIB-generated class, the original + * user-defined class is returned. */ public Class getBeanType() { - Class clazz = (this.bean instanceof String ? - this.beanFactory.getType((String) this.bean) : this.bean.getClass()); - return ClassUtils.getUserClass(clazz); + return this.beanType; } /** - * If the bean method is a bridge method, this method returns the bridged (user-defined) method. - * Otherwise it returns the same method as {@link #getMethod()}. + * If the bean method is a bridge method, this method returns the bridged + * (user-defined) method. Otherwise it returns the same method as {@link #getMethod()}. */ protected Method getBridgedMethod() { return this.bridgedMethod; @@ -199,8 +204,8 @@ public class HandlerMethod { } /** - * Returns a single annotation on the underlying method traversing its super methods if no - * annotation can be found on the given method itself. + * Returns a single annotation on the underlying method traversing its super methods + * if no annotation can be found on the given method itself. * @param annotationType the type of annotation to introspect the method for. * @return the annotation, or {@code null} if none found */ @@ -209,8 +214,8 @@ public class HandlerMethod { } /** - * If the provided instance contains a bean name rather than an object instance, the bean name is resolved - * before a {@link HandlerMethod} is created and returned. + * If the provided instance contains a bean name rather than an object instance, + * the bean name is resolved before a {@link HandlerMethod} is created and returned. */ public HandlerMethod createWithResolvedBean() { Object handler = this.bean; @@ -221,21 +226,22 @@ public class HandlerMethod { return new HandlerMethod(this, handler); } + @Override - public boolean equals(Object obj) { - if (this == obj) { + public boolean equals(Object other) { + if (this == other) { return true; } - if (obj != null && obj instanceof HandlerMethod) { - HandlerMethod other = (HandlerMethod) obj; - return (this.bean.equals(other.bean) && this.method.equals(other.method)); + if (!(other instanceof HandlerMethod)) { + return false; } - return false; + HandlerMethod otherMethod = (HandlerMethod) other; + return (this.bean.equals(otherMethod.bean) && this.method.equals(otherMethod.method)); } @Override public int hashCode() { - return this.bean.hashCode() * 31 + this.method.hashCode(); + return (this.bean.hashCode() * 31 + this.method.hashCode()); } @Override diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java index 2e02f62cf1..9860598fb0 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -40,8 +40,8 @@ import org.springframework.web.method.HandlerMethodSelector; import org.springframework.web.servlet.HandlerMapping; /** - * Abstract base class for {@link HandlerMapping} implementations that define a - * mapping between a request and a {@link HandlerMethod}. + * Abstract base class for {@link HandlerMapping} implementations that define + * a mapping between a request and a {@link HandlerMethod}. * *

For each registered handler method, a unique mapping is maintained with * subclasses defining the details of the mapping type {@code }. @@ -73,7 +73,6 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap private HandlerMethodMappingNamingStrategy namingStrategy; - private final Map handlerMethods = new LinkedHashMap(); private final MultiValueMap urlMap = new LinkedMultiValueMap(); @@ -96,8 +95,6 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap /** * Configure the naming strategy to use for assigning a default name to every * mapped handler method. - * - * @param namingStrategy strategy to use. */ public void setHandlerMethodMappingNamingStrategy(HandlerMethodMappingNamingStrategy namingStrategy) { this.namingStrategy = namingStrategy; @@ -118,6 +115,7 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap return this.nameMap.get(mappingName); } + /** * Detects handler methods at initialization. */ @@ -234,7 +232,6 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap } private void updateNameMap(String name, HandlerMethod newHandlerMethod) { - List handlerMethods = this.nameMap.get(name); if (handlerMethods != null) { for (HandlerMethod handlerMethod : handlerMethods) { @@ -266,7 +263,8 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap HandlerMethod handlerMethod; if (handler instanceof String) { String beanName = (String) handler; - handlerMethod = new HandlerMethod(beanName, getApplicationContext(), method); + handlerMethod = new HandlerMethod(beanName, + getApplicationContext().getAutowireCapableBeanFactory(), method); } else { handlerMethod = new HandlerMethod(handler, method); @@ -375,7 +373,7 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap * Return a comparator for sorting matching mappings. * The returned comparator should sort 'better' matches higher. * @param request the current request - * @return the comparator, never {@code null} + * @return the comparator (never {@code null}) */ protected abstract Comparator getMappingComparator(HttpServletRequest request);