public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
implements MatchableHandlerMapping, EmbeddedValueResolverAware {
//****省略****
@Override
public void afterPropertiesSet() {
//1.初始化配置
this.config = new RequestMappingInfo.BuilderConfiguration();
this.config.setUrlPathHelper(getUrlPathHelper());
this.config.setPathMatcher(getPathMatcher());
this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);
this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);
this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);
this.config.setContentNegotiationManager(getContentNegotiationManager());
//2.调用AbstractHandlerMethodMapping中afterPropertiesSet的逻辑
super.afterPropertiesSet();
}
//****省略****
}
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
protected void initHandlerMethods() {
//1.获取容器中全部的Bean的名称
String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) :
obtainApplicationContext().getBeanNamesForType(Object.class));
//2.根据名字获取类,判断该类是不是要转换的类型
for (String beanName : beanNames) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
Class<?> beanType = null;
try {
beanType = obtainApplicationContext().getType(beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
}
}
//3.处理有Controller注解和RequestMapping注解的Bean
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
}
//4.所有映射方法都处理完成之后的回调方法,交给子类扩展,我貌似尚未找到实现方法,或许以后会扩展
handlerMethodsInitialized(getHandlerMethods());
}
//根据Controller和RequestMapping注解来决定Bean是否需要处理
@Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
protected void detectHandlerMethods(final Object handler) {
//1.根据Bean名称获取Bean,或者根据类型获取Bean
Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
//2.获取类对象
final Class<?> userType = ClassUtils.getUserClass(handlerType);
//3.获取并且遍历类的所有方法
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
//4.getMappingForMethod方法用于返回处理器的对应方法,这个逻辑是在RequestMappingHandlerMapping
//中实现的,在AbstractHandlerMethodMapping中没有实现
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
//5.注册扫描到的handler的方法
for (Map.Entry<Method, T> entry : methods.entrySet()) {
//Aop方法的处理
Method invocableMethod = AopUtils.selectInvocableMethod(entry.getKey(), userType);
T mapping = entry.getValue();
registerHandlerMethod(handler, invocableMethod, mapping);
}
}
}
//注册扫描到的handler的方法,本质是保存在一个Map集合中
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
//注册请求和处理器映射关系
public void register(T mapping, Object handler, Method method) {
//1.加锁
this.readWriteLock.writeLock().lock();
try {
//2.新建HandlerMethod对象
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
assertUniqueMethodMapping(handlerMethod, mapping);
//3.加入mappingLookup,请求对象对应的全部处理方法对象映射集合
this.mappingLookup.put(mapping, handlerMethod);
List<String> directUrls = getDirectUrls(mapping);
//4.加入urlLookup,Url映射集合,获取请求路径,并将路径和处理器的映射关系保存到urlLookup
for (String url : directUrls) {
this.urlLookup.add(url, mapping);
}
//5.加入nameLookup,
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
//5.加入corsLookup,跨域相关
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
//6.加入registry集合 RequestMappingInfo -> MappingRegistration的映射关系
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();//解锁
}
}
@Override
@Nullable
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
//信息合并
info = typeInfo.combine(info);
}
}
return info;
}
private final MappingRegistry mappingRegistry = new MappingRegistry();
class MappingRegistry {
//RequestMappingInfo -> MappingRegistration的映射关系
private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
//RequestMappingInfo -> HandlerMethod的映射关系
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
//请求的Url -> RequestMappingInfo的映射关系,这里的T是一个LinkedHashMap,
//一个Url可能映射到多个RequestMappingInfo
//这些RequestMappingInfo就保存在一个LinkedHashMap里面
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();
}
AbstractApplicationContext#refresh
ConfigurableListableBeanFactory#preInstantiateSingletons
AbstractBeanFactory#getBean(java.lang.String)
AbstractBeanFactory#doGetBean
DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//1.获取到处理request的HandlerMethod对象(参考2.2)
Object handler = getHandlerInternal(request);
//2.没有获取到就使用默认的
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
//3.如果获取到的是String类型的BeanName,就从容器获取对应的Bean实例
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//4.获取执行链(获取执行链的细节和Spring监听器有关,可以后面再分析,即使自己没有写拦截器,默认也有框架内部的拦截器)
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
//5.支持跨域的请求处理,默认不是的
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
//6.返回执行链
return executionChain;
}
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//1.获取请求相对路径,比如"/hello"
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
//2.加读锁
this.mappingRegistry.acquireReadLock();
try {
//3.通过请求路径和请求对象寻找HandlerMethod处理对象
//HandlerMethod封装了目标方法等信息
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
if (logger.isDebugEnabled()) {
if (handlerMethod != null) {
logger.debug("Returning handler method [" + handlerMethod + "]");
}
else {
logger.debug("Did not find handler method for [" + lookupPath + "]");
}
}
//4.返回handlerMethod;createWithResolvedBean方法是将String类型的BeanName替换为从beanFactory获取的真正实例
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
//1.从urlLookup获取url对应映射的RequestMappingInfo集合
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
//2.如果找到了,就把加到matches这个匹配集合
if (directPathMatches != null) {
addMatchingMappings(directPathMatches, matches, request);
}
//3.如果集合为空,说明没找到,此时就扫描所有的映射集合
if (matches.isEmpty()) {
// No choice but to go through all mappings...
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
//4.找到最匹配的映射对象
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
if (CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
Match secondBestMatch = matches.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
}
}
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
通过请求对象获取HandlerMethod处理器对象->
先根据Url获取,如果获取失败则会根据全部集合去寻找,
如果匹配对象一样会抛出异常
然后根据HandlerMethod获取执行链HandlerExecutionChain
@Component
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("preHandle...");
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle ...");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("afterCompletion...");
}
}
@Component
public class RequestInterceptorRegister extends WebMvcConfigurerAdapter {
@Autowired
TestInterceptor testInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(testInterceptor).addPathPatterns("/**");
}
}
//AbstractHandlerMapping#initApplicationContext
@Override
protected void initApplicationContext() throws BeansException {
//1.空方法,子类扩展,子类可以在这里添加拦截器
extendInterceptors(this.interceptors);
//2.侦测容器中的MappedInterceptor,并添加到adaptedInterceptors属性集合(一个List)
detectMappedInterceptors(this.adaptedInterceptors);
initInterceptors();
}
protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
mappedInterceptors.addAll(
BeanFactoryUtils.beansOfTypeIncludingAncestors(obtainApplicationContext(), MappedInterceptor.class, true, false).values());
}
BeanFactoryUtils.beansOfTypeIncludingAncestors(obtainApplicationContext(), MappedInterceptor.class, true, false)
//WebMvcConfigurationSupport#line280
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
mapping.setOrder(0);//可以将断点打在这一行调试进入下面的getInterceptors方法
mapping.setInterceptors(getInterceptors()); //设置拦截器
mapping.setContentNegotiationManager(mvcContentNegotiationManager());
mapping.setCorsConfigurations(getCorsConfigurations());
PathMatchConfigurer configurer = getPathMatchConfigurer();
Boolean useSuffixPatternMatch = configurer.isUseSuffixPatternMatch();
Boolean useRegisteredSuffixPatternMatch = configurer.isUseRegisteredSuffixPatternMatch();
Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();
if (useSuffixPatternMatch != null) {
mapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
}
if (useRegisteredSuffixPatternMatch != null) {
mapping.setUseRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch);
}
if (useTrailingSlashMatch != null) {
mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
}
UrlPathHelper pathHelper = configurer.getUrlPathHelper();
if (pathHelper != null) {
mapping.setUrlPathHelper(pathHelper);
}
PathMatcher pathMatcher = configurer.getPathMatcher();
if (pathMatcher != null) {
mapping.setPathMatcher(pathMatcher);
}
return mapping;
}
//WebMvcConfigurationSupport#line329
protected final Object[] getInterceptors() {
//1.首次进来是null
if (this.interceptors == null) {
InterceptorRegistry registry = new InterceptorRegistry();
//2.将DelegatingWebMvcConfiguration的configurers中保存的拦截器添加到registry对象
addInterceptors(registry);
//3.添加系统拦截器
registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService()));
registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));
this.interceptors = registry.getInterceptors();
}
//4.返回全部拦截器
return this.interceptors.toArray();
}
@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
//1.遍历集合,将全部的连接器保存到configurers属性 (最终保存到了configurers对象的delegates属性)
this.configurers.addWebMvcConfigurers(configurers);
}
}
}
class WebMvcConfigurerComposite implements WebMvcConfigurer {
private final List<WebMvcConfigurer> delegates = new ArrayList<>();
public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.delegates.addAll(configurers);
}
}
}
//处理setConfigurers方法的调用栈,在populateBean阶段处理
AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement#inject(line 622)
DefaultListableBeanFactory#resolveDependency(line 1047)
DefaultListableBeanFactory#doResolveDependency(line 1072)
DefaultListableBeanFactory#resolveMultipleBeans(line 1158)
DefaultListableBeanFactory#findAutowireCandidates(line 1273)
BeanFactoryUtils#beanNamesForTypeIncludingAncestors(org.springframework.beans.factory.ListableBeanFactory, java.lang.Class<?>, boolean, boolean) (line 218)
DefaultListableBeanFactory#getBeanNamesForType(java.lang.Class<?>, boolean, boolean) (line 388)
DefaultListableBeanFactory#doGetBeanNamesForType (line405)
beanName=WebMvcConfigurer
requiredType=WebMvcConfigurer(我们定义的拦截器就是这个类型的子类)
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList<>();
// Check all bean definitions.
for (String beanName : this.beanDefinitionNames) {
// Only consider bean as eligible if the bean name
// is not defined as alias for some other bean.
if (!isAlias(beanName)) {
try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Only check bean definition if it is complete.
if (!mbd.isAbstract() && (allowEagerInit ||
((mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading())) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
// In case of FactoryBean, match object created by FactoryBean.
boolean isFactoryBean = isFactoryBean(beanName, mbd);
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
boolean matchFound =
(allowEagerInit || !isFactoryBean ||
(dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
(includeNonSingletons ||
(dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
isTypeMatch(beanName, type);
if (!matchFound && isFactoryBean) {
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191105201555785.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L215X21vbW9fY3Nkbg==,size_16,color_FFFFFF,t_70)
// In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
}
if (matchFound) {
result.add(beanName);
}
}
}
catch (CannotLoadBeanClassException ex) {
//省略...
}
}
}
//省略....
return StringUtils.toStringArray(result);
}
最后我们按照时序梳理一下:首先是扫描拦截器,流程如下:
在DelegatingWebMvcConfiguration的初始化过程,在其生命周期的属性注入阶段处理@Autowire的时候,通
过setConfigur方法,从beanDefinitionNames中创建并获取全部WebMvcConfigurer类型的Bean,然后保存在
其内部属性
在RequestMappingHandlerMapping的创建过程中,其构造方法中会调用setInterceptors初始化内部的拦截器
属性,这一步是在WebMvcConfigurationSupport中创建的,他会将子类DelegatingWebMvcConfiguration中已经
初始化好的拦截器赋值给RequestMappingHandlerMapping
RequestMappingHandlerMapping构造方法执行完毕之后,后面会经过Bean的生命周期中的InitializingBean接口回调,
借助该接口的afterPropertiesSet方法,在该方法中做初始化的过程,主要是在父类AbstractHandlerMethodMapping中
完成。他会从继承的ApplicationObjectSupport中获取到上下文容器applicationContext,从中获取到全部的Bean,然
后根据bean是否有Controller或者RequestMapping注解来决定是否需要处理这个Bean,对于我们写的Controller类肯定
是需要处理的,继而会获取上面的RequestMapping信息并封装成一个RequestMappingInfo对象,这里注意如果类型和方
法都添加了RequestMapping注解,会将两份信息都获取了并做合并。(RequestMapping注解既可以在类上也可以在方法上)。
然后将映射关系保存到Map集合,key是RequestMappingInfo对象或者Url,value是一个MappingRegistration对象,其内
部封装了RequestMappingInfo,处理方法(handlerMethod),Url(directUrls)等信息。
获取的时候,去RequestMappingHandlerMapping中获取处理器,首先会从请求对象中获取请求路径,根据Url去获取,
过程中会有一些完善机制,比如获取不到,异常等。获取到的是一个执行链,内部封装了目标方法和拦截器。