Skip to content

Commit 0f1bd49

Browse files
committed
HandlerMappingIntrospector is a bean
1 parent 126ac84 commit 0f1bd49

File tree

5 files changed

+124
-49
lines changed

5 files changed

+124
-49
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.springframework.util.PathMatcher;
3030
import org.springframework.web.cors.CorsConfiguration;
3131
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
32+
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
3233
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
3334
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
3435
import org.springframework.web.util.UrlPathHelper;
@@ -57,11 +58,14 @@ abstract class MvcNamespaceUtils {
5758

5859
private static final String CORS_CONFIGURATION_BEAN_NAME = "mvcCorsConfigurations";
5960

61+
private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
62+
6063

6164
public static void registerDefaultComponents(ParserContext parserContext, @Nullable Object source) {
6265
registerBeanNameUrlHandlerMapping(parserContext, source);
6366
registerHttpRequestHandlerAdapter(parserContext, source);
6467
registerSimpleControllerHandlerAdapter(parserContext, source);
68+
registerHandlerMappingIntrospector(parserContext, source);
6569
}
6670

6771
/**
@@ -186,6 +190,21 @@ else if (corsConfigurations != null) {
186190
return new RuntimeBeanReference(CORS_CONFIGURATION_BEAN_NAME);
187191
}
188192

193+
/**
194+
* Registers an {@link HandlerMappingIntrospector} under a well-known name
195+
* unless already registered.
196+
*/
197+
private static void registerHandlerMappingIntrospector(ParserContext parserContext, @Nullable Object source) {
198+
if (!parserContext.getRegistry().containsBeanDefinition(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)){
199+
RootBeanDefinition beanDef = new RootBeanDefinition(HandlerMappingIntrospector.class);
200+
beanDef.setSource(source);
201+
beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
202+
beanDef.setLazyInit(true);
203+
parserContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, beanDef);
204+
parserContext.registerComponent(new BeanComponentDefinition(beanDef, HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME));
205+
}
206+
}
207+
189208
/**
190209
* Find the {@code ContentNegotiationManager} bean created by or registered
191210
* with the {@code annotation-driven} element.

spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.springframework.context.ApplicationContextAware;
3333
import org.springframework.context.annotation.Bean;
3434
import org.springframework.context.annotation.Configuration;
35+
import org.springframework.context.annotation.Lazy;
3536
import org.springframework.core.convert.converter.Converter;
3637
import org.springframework.format.Formatter;
3738
import org.springframework.format.FormatterRegistry;
@@ -82,6 +83,7 @@
8283
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
8384
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
8485
import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite;
86+
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
8587
import org.springframework.web.servlet.mvc.Controller;
8688
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
8789
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
@@ -1022,6 +1024,12 @@ protected final Map<String, CorsConfiguration> getCorsConfigurations() {
10221024
protected void addCorsMappings(CorsRegistry registry) {
10231025
}
10241026

1027+
@Bean @Lazy
1028+
public HandlerMappingIntrospector mvcHandlerMappingIntrospector() {
1029+
return new HandlerMappingIntrospector();
1030+
}
1031+
1032+
10251033

10261034
private static final class EmptyHandlerMapping extends AbstractHandlerMapping {
10271035

spring-webmvc/src/main/java/org/springframework/web/servlet/handler/HandlerMappingIntrospector.java

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,23 @@
1818

1919
import java.io.IOException;
2020
import java.util.ArrayList;
21+
import java.util.Collections;
2122
import java.util.List;
2223
import java.util.Map;
2324
import java.util.Properties;
24-
2525
import javax.servlet.http.HttpServletRequest;
2626
import javax.servlet.http.HttpServletRequestWrapper;
2727

2828
import org.springframework.beans.factory.BeanFactoryUtils;
29+
import org.springframework.beans.factory.InitializingBean;
2930
import org.springframework.context.ApplicationContext;
31+
import org.springframework.context.ApplicationContextAware;
3032
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
3133
import org.springframework.core.io.ClassPathResource;
3234
import org.springframework.core.io.Resource;
3335
import org.springframework.core.io.support.PropertiesLoaderUtils;
3436
import org.springframework.lang.Nullable;
37+
import org.springframework.util.Assert;
3538
import org.springframework.util.ClassUtils;
3639
import org.springframework.util.StringUtils;
3740
import org.springframework.web.cors.CorsConfiguration;
@@ -56,33 +59,66 @@
5659
* @author Rossen Stoyanchev
5760
* @since 4.3.1
5861
*/
59-
public class HandlerMappingIntrospector implements CorsConfigurationSource {
62+
public class HandlerMappingIntrospector
63+
implements CorsConfigurationSource, ApplicationContextAware, InitializingBean {
64+
65+
@Nullable
66+
private ApplicationContext applicationContext;
67+
68+
@Nullable
69+
private List<HandlerMapping> handlerMappings;
6070

61-
private final List<HandlerMapping> handlerMappings;
6271

72+
/**
73+
* Constructor for use with {@link ApplicationContextAware}.
74+
*/
75+
public HandlerMappingIntrospector() {
76+
}
6377

6478
/**
6579
* Constructor that detects the configured {@code HandlerMapping}s in the
6680
* given {@code ApplicationContext} or falls back on
6781
* "DispatcherServlet.properties" like the {@code DispatcherServlet}.
6882
*/
83+
@Deprecated
6984
public HandlerMappingIntrospector(ApplicationContext context) {
7085
this.handlerMappings = initHandlerMappings(context);
7186
}
7287

7388

74-
private static List<HandlerMapping> initHandlerMappings(ApplicationContext context) {
89+
/**
90+
* Return the configured HandlerMapping's.
91+
*/
92+
public List<HandlerMapping> getHandlerMappings() {
93+
return this.handlerMappings;
94+
}
95+
96+
97+
@Override
98+
public void setApplicationContext(ApplicationContext applicationContext) {
99+
this.applicationContext = applicationContext;
100+
}
101+
102+
@Override
103+
public void afterPropertiesSet() {
104+
if (this.handlerMappings == null) {
105+
Assert.notNull(this.applicationContext, "No ApplicationContext");
106+
this.handlerMappings = initHandlerMappings(this.applicationContext);
107+
}
108+
}
109+
110+
private static List<HandlerMapping> initHandlerMappings(ApplicationContext applicationContext) {
75111
Map<String, HandlerMapping> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
76-
context, HandlerMapping.class, true, false);
112+
applicationContext, HandlerMapping.class, true, false);
77113
if (!beans.isEmpty()) {
78114
List<HandlerMapping> mappings = new ArrayList<>(beans.values());
79115
AnnotationAwareOrderComparator.sort(mappings);
80-
return mappings;
116+
return Collections.unmodifiableList(mappings);
81117
}
82-
return initDefaultHandlerMappings(context);
118+
return Collections.unmodifiableList(initFallback(applicationContext));
83119
}
84120

85-
private static List<HandlerMapping> initDefaultHandlerMappings(ApplicationContext context) {
121+
private static List<HandlerMapping> initFallback(ApplicationContext applicationContext) {
86122
Properties props;
87123
String path = "DispatcherServlet.properties";
88124
try {
@@ -99,7 +135,7 @@ private static List<HandlerMapping> initDefaultHandlerMappings(ApplicationContex
99135
for (String name : names) {
100136
try {
101137
Class<?> clazz = ClassUtils.forName(name, DispatcherServlet.class.getClassLoader());
102-
Object mapping = context.getAutowireCapableBeanFactory().createBean(clazz);
138+
Object mapping = applicationContext.getAutowireCapableBeanFactory().createBean(clazz);
103139
result.add((HandlerMapping) mapping);
104140
}
105141
catch (ClassNotFoundException ex) {
@@ -110,13 +146,6 @@ private static List<HandlerMapping> initDefaultHandlerMappings(ApplicationContex
110146
}
111147

112148

113-
/**
114-
* Return the configured HandlerMapping's.
115-
*/
116-
public List<HandlerMapping> getHandlerMappings() {
117-
return this.handlerMappings;
118-
}
119-
120149
/**
121150
* Find the {@link HandlerMapping} that would handle the given request and
122151
* return it as a {@link MatchableHandlerMapping} that can be used to test
@@ -129,6 +158,7 @@ public List<HandlerMapping> getHandlerMappings() {
129158
*/
130159
@Nullable
131160
public MatchableHandlerMapping getMatchableHandlerMapping(HttpServletRequest request) throws Exception {
161+
Assert.notNull(this.handlerMappings, "Handler mappings not initialized");
132162
HttpServletRequest wrapper = new RequestAttributeChangeIgnoringWrapper(request);
133163
for (HandlerMapping handlerMapping : this.handlerMappings) {
134164
Object handler = handlerMapping.getHandler(wrapper);
@@ -146,6 +176,7 @@ public MatchableHandlerMapping getMatchableHandlerMapping(HttpServletRequest req
146176
@Override
147177
@Nullable
148178
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
179+
Assert.notNull(this.handlerMappings, "Handler mappings not initialized");
149180
HttpServletRequest wrapper = new RequestAttributeChangeIgnoringWrapper(request);
150181
for (HandlerMapping handlerMapping : this.handlerMappings) {
151182
HandlerExecutionChain handler = null;

0 commit comments

Comments
 (0)