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 be8fd6d6107..ba8348b6752 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-2011 the original author or authors. + * Copyright 2002-2012 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,6 +30,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContextException; import org.springframework.util.ClassUtils; import org.springframework.util.LinkedMultiValueMap; @@ -42,18 +43,18 @@ import org.springframework.web.servlet.HandlerMapping; /** * 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 }. - * + * + *

For each registered handler method, a unique mapping is maintained with + * subclasses defining the details of the mapping type {@code }. + * * @param The mapping for a {@link HandlerMethod} containing the conditions - * needed to match the handler method to incoming request. - * + * needed to match the handler method to incoming request. + * * @author Arjen Poutsma * @author Rossen Stoyanchev * @since 3.1 */ -public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMapping { +public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMapping implements InitializingBean { private boolean detectHandlerMethodsInAncestorContexts = false; @@ -72,7 +73,7 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap public void setDetectHandlerMethodsInAncestorContexts(boolean detectHandlerMethodsInAncestorContexts) { this.detectHandlerMethodsInAncestorContexts = detectHandlerMethodsInAncestorContexts; } - + /** * Return a map with all handler methods and their mappings. */ @@ -81,11 +82,17 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap } /** - * ApplicationContext initialization and handler method detection. + * ApplicationContext initialization. */ @Override public void initApplicationContext() throws ApplicationContextException { super.initApplicationContext(); + } + + /** + * Detects handler methods at initialization. + */ + public void afterPropertiesSet() { initHandlerMethods(); } @@ -99,7 +106,7 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap if (logger.isDebugEnabled()) { logger.debug("Looking for request mappings in application context: " + getApplicationContext()); } - + String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) : getApplicationContext().getBeanNamesForType(Object.class)); @@ -131,17 +138,17 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap * @param handler the bean name of a handler or a handler instance */ protected void detectHandlerMethods(final Object handler) { - Class handlerType = (handler instanceof String) ? + Class handlerType = (handler instanceof String) ? getApplicationContext().getType((String) handler) : handler.getClass(); final Class userType = ClassUtils.getUserClass(handlerType); - + Set methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() { public boolean matches(Method method) { return getMappingForMethod(method, userType) != null; } }); - + for (Method method : methods) { T mapping = getMappingForMethod(method, userType); registerHandlerMethod(handler, method, mapping); @@ -149,7 +156,7 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap } /** - * Provide the mapping for a handler method. A method for which no + * Provide the mapping for a handler method. A method for which no * mapping can be provided is not a handler method. * * @param method the method to provide a mapping for @@ -161,11 +168,11 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap /** * Register a handler method and its unique mapping. - * + * * @param handler the bean name of the handler or the handler instance * @param method the method to register * @param mapping the mapping conditions associated with the handler method - * @throws IllegalStateException if another method was already registered + * @throws IllegalStateException if another method was already registered * under the same mapping */ protected void registerHandlerMethod(Object handler, Method method, T mapping) { @@ -177,19 +184,19 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap else { handlerMethod = new HandlerMethod(handler, method); } - + HandlerMethod oldHandlerMethod = handlerMethods.get(mapping); if (oldHandlerMethod != null && !oldHandlerMethod.equals(handlerMethod)) { throw new IllegalStateException("Ambiguous mapping found. Cannot map '" + handlerMethod.getBean() + "' bean method \n" + handlerMethod + "\nto " + mapping + ": There is already '" + oldHandlerMethod.getBean() + "' bean method\n" + oldHandlerMethod + " mapped."); } - + handlerMethods.put(mapping, handlerMethod); if (logger.isInfoEnabled()) { logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod); } - + Set patterns = getMappingPathPatterns(mapping); for (String pattern : patterns) { if (!getPathMatcher().isPattern(pattern)) { @@ -199,7 +206,7 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap } /** - * Extract and return the URL paths contained in a mapping. + * Extract and return the URL paths contained in a mapping. */ protected abstract Set getMappingPathPatterns(T mapping); @@ -230,11 +237,11 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap /** * Look up the best-matching handler method for the current request. * If multiple matches are found, the best match is selected. - * + * * @param lookupPath mapping lookup path within the current servlet mapping * @param request the current request * @return the best-matching handler method, or {@code null} if no match - * + * * @see #handleMatch(Object, String, HttpServletRequest) * @see #handleNoMatch(Set, String, HttpServletRequest) */ @@ -289,7 +296,7 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap } /** - * Check if a mapping matches the current request and return a (potentially + * Check if a mapping matches the current request and return a (potentially * new) mapping with conditions relevant to the current request. * * @param mapping the mapping to get a match for @@ -308,7 +315,7 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap /** * Invoked when a matching mapping is found. - * @param mapping the matching mapping + * @param mapping the matching mapping * @param lookupPath mapping lookup path within the current servlet mapping * @param request the current request */ @@ -360,5 +367,5 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap return comparator.compare(match1.mapping, match2.mapping); } } - + } \ No newline at end of file diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java index 8dc615c4af6..8d1c8c8112a 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java @@ -83,6 +83,7 @@ public class WebMvcConfigurationSupportTests { assertEquals(0, handlerMapping.getOrder()); handlerMapping.setApplicationContext(cxt); + handlerMapping.afterPropertiesSet(); HandlerExecutionChain chain = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/")); assertNotNull(chain.getInterceptors()); assertEquals(ConversionServiceExposingInterceptor.class, chain.getInterceptors()[0].getClass()); @@ -204,6 +205,7 @@ public class WebMvcConfigurationSupportTests { RequestMappingHandlerMapping rmHandlerMapping = webConfig.requestMappingHandlerMapping(); rmHandlerMapping.setApplicationContext(appCxt); + rmHandlerMapping.afterPropertiesSet(); HandlerExecutionChain chain = rmHandlerMapping.getHandler(new MockHttpServletRequest("GET", "/")); assertNotNull(chain.getInterceptors()); assertEquals(2, chain.getInterceptors().length); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/HandlerMethodMappingTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/HandlerMethodMappingTests.java index 755eb6a62d0..7524a63dd79 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/HandlerMethodMappingTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/HandlerMethodMappingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -82,7 +82,7 @@ public class HandlerMethodMappingTests { HandlerMethod result = mapping.getHandlerInternal(new MockHttpServletRequest("GET", "/foo")); assertEquals(method1, result.getMethod()); } - + @Test(expected = IllegalStateException.class) public void ambiguousMatch() throws Exception { mapping.registerHandlerMethod(handler, method1, "/f?o"); @@ -95,24 +95,26 @@ public class HandlerMethodMappingTests { public void testDetectHandlerMethodsInAncestorContexts() { StaticApplicationContext cxt = new StaticApplicationContext(); cxt.registerSingleton("myHandler", MyHandler.class); - + AbstractHandlerMethodMapping mapping1 = new MyHandlerMethodMapping(); mapping1.setApplicationContext(new StaticApplicationContext(cxt)); + mapping1.afterPropertiesSet(); assertEquals(0, mapping1.getHandlerMethods().size()); AbstractHandlerMethodMapping mapping2 = new MyHandlerMethodMapping(); mapping2.setDetectHandlerMethodsInAncestorContexts(true); mapping2.setApplicationContext(new StaticApplicationContext(cxt)); + mapping2.afterPropertiesSet(); assertEquals(2, mapping2.getHandlerMethods().size()); } - + private static class MyHandlerMethodMapping extends AbstractHandlerMethodMapping { private UrlPathHelper pathHelper = new UrlPathHelper(); - + private PathMatcher pathMatcher = new AntPathMatcher(); @Override diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HandlerMethodAnnotationDetectionTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HandlerMethodAnnotationDetectionTests.java index 3816f4b5de8..cedaf44cfac 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HandlerMethodAnnotationDetectionTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HandlerMethodAnnotationDetectionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -103,6 +103,7 @@ public class HandlerMethodAnnotationDetectionTests { context.refresh(); handlerMapping.setApplicationContext(context); + handlerMapping.afterPropertiesSet(); handlerAdapter.afterPropertiesSet(); exceptionResolver.afterPropertiesSet(); } diff --git a/src/dist/changelog.txt b/src/dist/changelog.txt index 1c94b659184..62668e91f37 100644 --- a/src/dist/changelog.txt +++ b/src/dist/changelog.txt @@ -16,6 +16,7 @@ Changes in version 3.2 M1 * add Jackson 2 HttpMessageConverter and View types * add pretty print option to Jackson HttpMessageConverter and View types * fix issue with resolving Errors controller method argument +* detect controller methods via InitializingBean in RequestMappingHandlerMapping Changes in version 3.1.1 (2012-02-16) -------------------------------------