From b6ca8a90187092a3f6d039dc538909ac3fcdf1c3 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Wed, 27 Sep 2017 21:28:49 -0400 Subject: [PATCH] HandlerMappingIntrospector is a bean --- .../web/servlet/config/MvcNamespaceUtils.java | 19 ++++++ .../WebMvcConfigurationSupport.java | 8 +++ .../handler/HandlerMappingIntrospector.java | 60 ++++++++++++++----- .../web/servlet/config/MvcNamespaceTests.java | 55 +++++++++-------- .../HandlerMappingIntrospectorTests.java | 28 ++++++--- 5 files changed, 122 insertions(+), 48 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java index 72eecdd849f..4e585619969 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java @@ -28,6 +28,7 @@ import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping; +import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter; import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter; import org.springframework.web.util.UrlPathHelper; @@ -56,11 +57,14 @@ abstract class MvcNamespaceUtils { private static final String CORS_CONFIGURATION_BEAN_NAME = "mvcCorsConfigurations"; + private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"; + public static void registerDefaultComponents(ParserContext parserContext, Object source) { registerBeanNameUrlHandlerMapping(parserContext, source); registerHttpRequestHandlerAdapter(parserContext, source); registerSimpleControllerHandlerAdapter(parserContext, source); + registerHandlerMappingIntrospector(parserContext, source); } /** @@ -184,6 +188,21 @@ abstract class MvcNamespaceUtils { return new RuntimeBeanReference(CORS_CONFIGURATION_BEAN_NAME); } + /** + * Registers an {@link HandlerMappingIntrospector} under a well-known name + * unless already registered. + */ + private static void registerHandlerMappingIntrospector(ParserContext parserContext, Object source) { + if (!parserContext.getRegistry().containsBeanDefinition(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)){ + RootBeanDefinition beanDef = new RootBeanDefinition(HandlerMappingIntrospector.class); + beanDef.setSource(source); + beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + beanDef.setLazyInit(true); + parserContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, beanDef); + parserContext.registerComponent(new BeanComponentDefinition(beanDef, HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)); + } + } + /** * Find the {@code ContentNegotiationManager} bean created by or registered * with the {@code annotation-driven} element. diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java index dd3c2dcffbe..20f5d0da297 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java @@ -33,6 +33,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; import org.springframework.core.convert.converter.Converter; import org.springframework.format.Formatter; import org.springframework.format.FormatterRegistry; @@ -77,6 +78,7 @@ import org.springframework.web.servlet.handler.AbstractHandlerMapping; import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping; import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor; import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite; +import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import org.springframework.web.servlet.mvc.Controller; import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter; import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter; @@ -954,6 +956,12 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv protected void addCorsMappings(CorsRegistry registry) { } + @Bean @Lazy + public HandlerMappingIntrospector mvcHandlerMappingIntrospector() { + return new HandlerMappingIntrospector(); + } + + private static final class EmptyHandlerMapping extends AbstractHandlerMapping { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/HandlerMappingIntrospector.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/HandlerMappingIntrospector.java index 1c7fa9b6b38..220789ef5ad 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/HandlerMappingIntrospector.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/HandlerMappingIntrospector.java @@ -18,6 +18,7 @@ package org.springframework.web.servlet.handler; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; @@ -25,11 +26,14 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PropertiesLoaderUtils; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.springframework.web.cors.CorsConfiguration; @@ -54,33 +58,64 @@ import org.springframework.web.servlet.HandlerMapping; * @author Rossen Stoyanchev * @since 4.3.1 */ -public class HandlerMappingIntrospector implements CorsConfigurationSource { +public class HandlerMappingIntrospector + implements CorsConfigurationSource, ApplicationContextAware, InitializingBean { - private final List handlerMappings; + private ApplicationContext applicationContext; + private List handlerMappings; + + + /** + * Constructor for use with {@link ApplicationContextAware}. + */ + public HandlerMappingIntrospector() { + } /** * Constructor that detects the configured {@code HandlerMapping}s in the * given {@code ApplicationContext} or falls back on * "DispatcherServlet.properties" like the {@code DispatcherServlet}. */ + @Deprecated public HandlerMappingIntrospector(ApplicationContext context) { this.handlerMappings = initHandlerMappings(context); } - private static List initHandlerMappings(ApplicationContext context) { + /** + * Return the configured HandlerMapping's. + */ + public List getHandlerMappings() { + return this.handlerMappings; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + @Override + public void afterPropertiesSet() { + if (this.handlerMappings == null) { + Assert.notNull(this.applicationContext, "No ApplicationContext"); + this.handlerMappings = initHandlerMappings(this.applicationContext); + } + } + + private static List initHandlerMappings(ApplicationContext applicationContext) { Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors( - context, HandlerMapping.class, true, false); + applicationContext, HandlerMapping.class, true, false); if (!beans.isEmpty()) { List mappings = new ArrayList(beans.values()); AnnotationAwareOrderComparator.sort(mappings); - return mappings; + return Collections.unmodifiableList(mappings); } - return initDefaultHandlerMappings(context); + return Collections.unmodifiableList(initFallback(applicationContext)); } - private static List initDefaultHandlerMappings(ApplicationContext context) { + private static List initFallback(ApplicationContext applicationContext) { Properties props; String path = "DispatcherServlet.properties"; try { @@ -97,7 +132,7 @@ public class HandlerMappingIntrospector implements CorsConfigurationSource { for (String name : names) { try { Class clazz = ClassUtils.forName(name, DispatcherServlet.class.getClassLoader()); - Object mapping = context.getAutowireCapableBeanFactory().createBean(clazz); + Object mapping = applicationContext.getAutowireCapableBeanFactory().createBean(clazz); result.add((HandlerMapping) mapping); } catch (ClassNotFoundException ex) { @@ -108,13 +143,6 @@ public class HandlerMappingIntrospector implements CorsConfigurationSource { } - /** - * Return the configured HandlerMapping's. - */ - public List getHandlerMappings() { - return this.handlerMappings; - } - /** * Find the {@link HandlerMapping} that would handle the given request and * return it as a {@link MatchableHandlerMapping} that can be used to test @@ -126,6 +154,7 @@ public class HandlerMappingIntrospector implements CorsConfigurationSource { * @throws Exception if any of the HandlerMapping's raise an exception */ public MatchableHandlerMapping getMatchableHandlerMapping(HttpServletRequest request) throws Exception { + Assert.notNull(this.handlerMappings, "Handler mappings not initialized"); HttpServletRequest wrapper = new RequestAttributeChangeIgnoringWrapper(request); for (HandlerMapping handlerMapping : this.handlerMappings) { Object handler = handlerMapping.getHandler(wrapper); @@ -142,6 +171,7 @@ public class HandlerMappingIntrospector implements CorsConfigurationSource { @Override public CorsConfiguration getCorsConfiguration(HttpServletRequest request) { + Assert.notNull(this.handlerMappings, "Handler mappings not initialized"); HttpServletRequest wrapper = new RequestAttributeChangeIgnoringWrapper(request); for (HandlerMapping handlerMapping : this.handlerMappings) { HandlerExecutionChain handler = null; diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java index d54c28772d1..0aa7fa2306f 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java @@ -97,6 +97,7 @@ import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.handler.AbstractHandlerMapping; import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping; import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor; +import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import org.springframework.web.servlet.handler.MappedInterceptor; import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; import org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor; @@ -189,7 +190,7 @@ public class MvcNamespaceTests { @Test public void testDefaultConfig() throws Exception { - loadBeanDefinitions("mvc-config.xml", 14); + loadBeanDefinitions("mvc-config.xml"); RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class); assertNotNull(mapping); @@ -248,11 +249,18 @@ public class MvcNamespaceTests { CompositeUriComponentsContributor.class); assertNotNull(uriComponentsContributor); + + String name = "mvcHandlerMappingIntrospector"; + HandlerMappingIntrospector introspector = this.appContext.getBean(name, HandlerMappingIntrospector.class); + assertNotNull(introspector); + assertEquals(2, introspector.getHandlerMappings().size()); + assertSame(mapping, introspector.getHandlerMappings().get(0)); + assertEquals(BeanNameUrlHandlerMapping.class, introspector.getHandlerMappings().get(1).getClass()); } @Test(expected = TypeMismatchException.class) public void testCustomConversionService() throws Exception { - loadBeanDefinitions("mvc-config-custom-conversion-service.xml", 14); + loadBeanDefinitions("mvc-config-custom-conversion-service.xml"); RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class); assertNotNull(mapping); @@ -287,7 +295,7 @@ public class MvcNamespaceTests { } private void doTestCustomValidator(String xml) throws Exception { - loadBeanDefinitions(xml, 14); + loadBeanDefinitions(xml); RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class); assertNotNull(mapping); @@ -309,7 +317,7 @@ public class MvcNamespaceTests { @Test public void testInterceptors() throws Exception { - loadBeanDefinitions("mvc-config-interceptors.xml", 21); + loadBeanDefinitions("mvc-config-interceptors.xml"); RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class); assertNotNull(mapping); @@ -345,7 +353,7 @@ public class MvcNamespaceTests { @Test public void testResources() throws Exception { - loadBeanDefinitions("mvc-config-resources.xml", 20); + loadBeanDefinitions("mvc-config-resources.xml"); HttpRequestHandlerAdapter adapter = appContext.getBean(HttpRequestHandlerAdapter.class); assertNotNull(adapter); @@ -393,7 +401,7 @@ public class MvcNamespaceTests { @Test public void testResourcesWithOptionalAttributes() throws Exception { - loadBeanDefinitions("mvc-config-resources-optional-attrs.xml", 10); + loadBeanDefinitions("mvc-config-resources-optional-attrs.xml"); SimpleUrlHandlerMapping mapping = appContext.getBean(SimpleUrlHandlerMapping.class); assertNotNull(mapping); @@ -408,7 +416,7 @@ public class MvcNamespaceTests { @Test public void testResourcesWithResolversTransformers() throws Exception { - loadBeanDefinitions("mvc-config-resources-chain.xml", 11); + loadBeanDefinitions("mvc-config-resources-chain.xml"); SimpleUrlHandlerMapping mapping = appContext.getBean(SimpleUrlHandlerMapping.class); assertNotNull(mapping); @@ -447,7 +455,7 @@ public class MvcNamespaceTests { @Test public void testResourcesWithResolversTransformersCustom() throws Exception { - loadBeanDefinitions("mvc-config-resources-chain-no-auto.xml", 12); + loadBeanDefinitions("mvc-config-resources-chain-no-auto.xml"); SimpleUrlHandlerMapping mapping = appContext.getBean(SimpleUrlHandlerMapping.class); assertNotNull(mapping); @@ -480,7 +488,7 @@ public class MvcNamespaceTests { @Test public void testDefaultServletHandler() throws Exception { - loadBeanDefinitions("mvc-config-default-servlet.xml", 6); + loadBeanDefinitions("mvc-config-default-servlet.xml"); HttpRequestHandlerAdapter adapter = appContext.getBean(HttpRequestHandlerAdapter.class); assertNotNull(adapter); @@ -506,7 +514,7 @@ public class MvcNamespaceTests { @Test public void testDefaultServletHandlerWithOptionalAttributes() throws Exception { - loadBeanDefinitions("mvc-config-default-servlet-optional-attrs.xml", 6); + loadBeanDefinitions("mvc-config-default-servlet-optional-attrs.xml"); HttpRequestHandlerAdapter adapter = appContext.getBean(HttpRequestHandlerAdapter.class); assertNotNull(adapter); @@ -532,7 +540,7 @@ public class MvcNamespaceTests { @Test public void testBeanDecoration() throws Exception { - loadBeanDefinitions("mvc-config-bean-decoration.xml", 16); + loadBeanDefinitions("mvc-config-bean-decoration.xml"); RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class); assertNotNull(mapping); @@ -553,7 +561,7 @@ public class MvcNamespaceTests { @Test public void testViewControllers() throws Exception { - loadBeanDefinitions("mvc-config-view-controllers.xml", 19); + loadBeanDefinitions("mvc-config-view-controllers.xml"); RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class); assertNotNull(mapping); @@ -634,7 +642,7 @@ public class MvcNamespaceTests { /** WebSphere gives trailing servlet path slashes by default!! */ @Test public void testViewControllersOnWebSphere() throws Exception { - loadBeanDefinitions("mvc-config-view-controllers.xml", 19); + loadBeanDefinitions("mvc-config-view-controllers.xml"); SimpleUrlHandlerMapping mapping2 = appContext.getBean(SimpleUrlHandlerMapping.class); SimpleControllerHandlerAdapter adapter = appContext.getBean(SimpleControllerHandlerAdapter.class); @@ -678,7 +686,7 @@ public class MvcNamespaceTests { @Test public void testViewControllersDefaultConfig() { - loadBeanDefinitions("mvc-config-view-controllers-minimal.xml", 7); + loadBeanDefinitions("mvc-config-view-controllers-minimal.xml"); SimpleUrlHandlerMapping hm = this.appContext.getBean(SimpleUrlHandlerMapping.class); assertNotNull(hm); @@ -701,7 +709,7 @@ public class MvcNamespaceTests { @Test public void testContentNegotiationManager() throws Exception { - loadBeanDefinitions("mvc-config-content-negotiation-manager.xml", 15); + loadBeanDefinitions("mvc-config-content-negotiation-manager.xml"); RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class); ContentNegotiationManager manager = mapping.getContentNegotiationManager(); @@ -723,7 +731,7 @@ public class MvcNamespaceTests { @Test public void testAsyncSupportOptions() throws Exception { - loadBeanDefinitions("mvc-config-async-support.xml", 15); + loadBeanDefinitions("mvc-config-async-support.xml"); RequestMappingHandlerAdapter adapter = appContext.getBean(RequestMappingHandlerAdapter.class); assertNotNull(adapter); @@ -743,7 +751,7 @@ public class MvcNamespaceTests { @Test public void testViewResolution() throws Exception { - loadBeanDefinitions("mvc-config-view-resolution.xml", 7); + loadBeanDefinitions("mvc-config-view-resolution.xml"); ViewResolverComposite compositeResolver = this.appContext.getBean(ViewResolverComposite.class); assertNotNull(compositeResolver); @@ -834,7 +842,7 @@ public class MvcNamespaceTests { @Test public void testViewResolutionWithContentNegotiation() throws Exception { - loadBeanDefinitions("mvc-config-view-resolution-content-negotiation.xml", 7); + loadBeanDefinitions("mvc-config-view-resolution-content-negotiation.xml"); ViewResolverComposite compositeResolver = this.appContext.getBean(ViewResolverComposite.class); assertNotNull(compositeResolver); @@ -858,7 +866,7 @@ public class MvcNamespaceTests { @Test public void testViewResolutionWithOrderSet() throws Exception { - loadBeanDefinitions("mvc-config-view-resolution-custom-order.xml", 1); + loadBeanDefinitions("mvc-config-view-resolution-custom-order.xml"); ViewResolverComposite compositeResolver = this.appContext.getBean(ViewResolverComposite.class); assertNotNull(compositeResolver); @@ -868,7 +876,7 @@ public class MvcNamespaceTests { @Test public void testPathMatchingHandlerMappings() throws Exception { - loadBeanDefinitions("mvc-config-path-matching-mappings.xml", 23); + loadBeanDefinitions("mvc-config-path-matching-mappings.xml"); RequestMappingHandlerMapping requestMapping = appContext.getBean(RequestMappingHandlerMapping.class); assertNotNull(requestMapping); @@ -889,7 +897,7 @@ public class MvcNamespaceTests { @Test public void testCorsMinimal() throws Exception { - loadBeanDefinitions("mvc-config-cors-minimal.xml", 14); + loadBeanDefinitions("mvc-config-cors-minimal.xml"); String[] beanNames = appContext.getBeanNamesForType(AbstractHandlerMapping.class); assertEquals(2, beanNames.length); @@ -912,7 +920,7 @@ public class MvcNamespaceTests { @Test public void testCors() throws Exception { - loadBeanDefinitions("mvc-config-cors.xml", 14); + loadBeanDefinitions("mvc-config-cors.xml"); String[] beanNames = appContext.getBeanNamesForType(AbstractHandlerMapping.class); assertEquals(2, beanNames.length); @@ -941,12 +949,11 @@ public class MvcNamespaceTests { } - private void loadBeanDefinitions(String fileName, int expectedBeanCount) { + private void loadBeanDefinitions(String fileName) { XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(appContext); ClassPathResource resource = new ClassPathResource(fileName, AnnotationDrivenBeanDefinitionParserTests.class); reader.loadBeanDefinitions(resource); String names = Arrays.toString(this.appContext.getBeanDefinitionNames()); - assertEquals("Bean names: " + names, expectedBeanCount, appContext.getBeanDefinitionCount()); appContext.refresh(); } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/HandlerMappingIntrospectorTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/HandlerMappingIntrospectorTests.java index d3bf4853f0f..cae57839db8 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/HandlerMappingIntrospectorTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/HandlerMappingIntrospectorTests.java @@ -31,6 +31,7 @@ import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.context.support.StaticWebApplicationContext; import org.springframework.web.cors.CorsConfiguration; @@ -38,8 +39,10 @@ import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; -import static org.junit.Assert.*; -import static org.springframework.web.servlet.HandlerMapping.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.springframework.web.servlet.HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE; /** * Unit tests for {@link HandlerMappingIntrospector}. @@ -58,7 +61,7 @@ public class HandlerMappingIntrospectorTests { cxt.refresh(); List expected = Arrays.asList(cxt.getBean("hmA"), cxt.getBean("hmB"), cxt.getBean("hmC")); - List actual = new HandlerMappingIntrospector(cxt).getHandlerMappings(); + List actual = getIntrospector(cxt).getHandlerMappings(); assertEquals(expected, actual); } @@ -75,7 +78,7 @@ public class HandlerMappingIntrospectorTests { cxt.refresh(); List expected = Arrays.asList(cxt.getBean("hmC"), cxt.getBean("hmB"), cxt.getBean("hmA")); - List actual = new HandlerMappingIntrospector(cxt).getHandlerMappings(); + List actual = getIntrospector(cxt).getHandlerMappings(); assertEquals(expected, actual); } @@ -85,7 +88,7 @@ public class HandlerMappingIntrospectorTests { StaticWebApplicationContext cxt = new StaticWebApplicationContext(); cxt.refresh(); - List actual = new HandlerMappingIntrospector(cxt).getHandlerMappings(); + List actual = getIntrospector(cxt).getHandlerMappings(); assertEquals(2, actual.size()); assertEquals(BeanNameUrlHandlerMapping.class, actual.get(0).getClass()); assertEquals(org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping.class, @@ -102,7 +105,7 @@ public class HandlerMappingIntrospectorTests { cxt.refresh(); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/path"); - MatchableHandlerMapping hm = new HandlerMappingIntrospector(cxt).getMatchableHandlerMapping(request); + MatchableHandlerMapping hm = getIntrospector(cxt).getMatchableHandlerMapping(request); assertEquals(cxt.getBean("hm"), hm); assertNull("Attributes changes not ignored", request.getAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE)); @@ -115,7 +118,7 @@ public class HandlerMappingIntrospectorTests { cxt.refresh(); MockHttpServletRequest request = new MockHttpServletRequest(); - new HandlerMappingIntrospector(cxt).getMatchableHandlerMapping(request); + getIntrospector(cxt).getMatchableHandlerMapping(request); } @Test @@ -129,7 +132,7 @@ public class HandlerMappingIntrospectorTests { MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/path"); request.addHeader("Origin", "http://localhost:9000"); request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "POST"); - CorsConfiguration corsConfig = new HandlerMappingIntrospector(cxt).getCorsConfiguration(request); + CorsConfiguration corsConfig = getIntrospector(cxt).getCorsConfiguration(request); assertNotNull(corsConfig); assertEquals(Collections.singletonList("http://localhost:9000"), corsConfig.getAllowedOrigins()); @@ -144,13 +147,20 @@ public class HandlerMappingIntrospectorTests { MockHttpServletRequest request = new MockHttpServletRequest("POST", "/path"); request.addHeader("Origin", "http://localhost:9000"); - CorsConfiguration corsConfig = new HandlerMappingIntrospector(cxt).getCorsConfiguration(request); + CorsConfiguration corsConfig = getIntrospector(cxt).getCorsConfiguration(request); assertNotNull(corsConfig); assertEquals(Collections.singletonList("http://localhost:9000"), corsConfig.getAllowedOrigins()); assertEquals(Collections.singletonList("POST"), corsConfig.getAllowedMethods()); } + private HandlerMappingIntrospector getIntrospector(WebApplicationContext cxt) { + HandlerMappingIntrospector introspector = new HandlerMappingIntrospector(); + introspector.setApplicationContext(cxt); + introspector.afterPropertiesSet(); + return introspector; + } + private static class TestHandlerMapping implements HandlerMapping {