SpringMVC源码剖析2——处理器映射器
![](https://i-blog.csdnimg.cn/blog_migrate/c1122b35a847f511b1ba489f59f662ef.png)
01.处理器映射器 HandlerMapping
一句话概括作用: 为 我 们 建 立 起 @RequestMapping 注 解 和 控 制 器 方 法 的 对 应 关 系 。
怎么去查看
第一步:
处理器映射器的实体类:
RequestMappingHandlerMapping
父类
RequestMappingInfoHandlerMapping
父类的父类
AbstractHandlerMethodMapping
父类的父类的父类
AbstractHandlerMapping
第二步:找到对应的方法,获取拦截的方法
![](https://i-blog.csdnimg.cn/blog_migrate/da13b0fa0f291945fac268f3c6447e3b.png)
此处能看到一个无界HashMap,存储的是映射关系
那么什么时候存进去的呢?
在AbstractHandlerMethodMapping类中有如下代码:
扫描ApplicationContext中的bean,检测并注册处理程序方法。用来扫描bean的
上述方法将扫描到的Colltroler类当做参数传递到下面的方法,通过反射获取.class字节码,然后再通过反射将方法和方法上面的路径找到存到map中
detectHandlerMethods(beanName);
registerHandlerMethod(handler, invocableMethod, mapping);
注册处理程序方法及其唯一映射。在启动时调用
先加锁,后将方法和映射放入Map中的
register(mapping, handler, method);
一句话概括作用: 为 我 们 建 立 起 @RequestMapping 注 解 和 控 制 器 方 法 的 对 应 关 系 。
怎么去查看
第一步:
处理器映射器的实体类:
RequestMappingHandlerMapping
父类
RequestMappingInfoHandlerMapping
父类的父类
AbstractHandlerMethodMapping
父类的父类的父类
AbstractHandlerMapping
第二步:找到对应的方法,获取拦截的方法
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
public Map<T, HandlerMethod> getHandlerMethods() {
this .mappingRegistry.acquireReadLock();
try {
return Collections.unmodifiableMap( this .mappingRegistry.getMappings());
}
finally {
this .mappingRegistry.releaseReadLock();
}
}
getMappings()代码内容
public Map<T, HandlerMethod> getMappings() {
return this .mappingLookup;
}
|
![](https://i-blog.csdnimg.cn/blog_migrate/da13b0fa0f291945fac268f3c6447e3b.png)
此处能看到一个无界HashMap,存储的是映射关系
那么什么时候存进去的呢?
在AbstractHandlerMethodMapping类中有如下代码:
扫描ApplicationContext中的bean,检测并注册处理程序方法。用来扫描bean的
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug( "Looking for request mappings in application context: " + getApplicationContext());
}
String[] beanNames = ( this .detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object. class ) :
obtainApplicationContext().getBeanNamesForType(Object. class ));
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);
}
}
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
}
handlerMethodsInitialized(getHandlerMethods());
}
|
上述方法将扫描到的Colltroler类当做参数传递到下面的方法,通过反射获取.class字节码,然后再通过反射将方法和方法上面的路径找到存到map中
detectHandlerMethods(beanName);
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
protected void detectHandlerMethods( final Object handler) {
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null ) {
final Class<?> userType = ClassUtils.getUserClass(handlerType);
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException( "Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
if (logger.isDebugEnabled()) {
logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods);
}
for (Map.Entry<Method, T> entry : methods.entrySet()) {
Method invocableMethod = AopUtils.selectInvocableMethod(entry.getKey(), userType);
T mapping = entry.getValue();
registerHandlerMethod(handler, invocableMethod, mapping);
}
}
}
|
registerHandlerMethod(handler, invocableMethod, mapping);
注册处理程序方法及其唯一映射。在启动时调用
[Java] 纯文本查看 复制代码
1
2
3
|
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this .mappingRegistry.register(mapping, handler, method);
}
|
先加锁,后将方法和映射放入Map中的
register(mapping, handler, method);
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
public void register(T mapping, Object handler, Method method) {
this .readWriteLock.writeLock().lock();
try {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
assertUniqueMethodMapping(handlerMethod, mapping);
if (logger.isInfoEnabled()) {
logger.info( "Mapped \"" + mapping + "\" onto " + handlerMethod);
}
this .mappingLookup.put(mapping, handlerMethod);
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
this .urlLookup.add(url, mapping);
}
String name = null ;
if (getNamingStrategy() != null ) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null ) {
this .corsLookup.put(handlerMethod, corsConfig);
}
this .registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
this .readWriteLock.writeLock().unlock();
}
}
|