RequestMappingHandlerMapping 类结构
继承结构:
RequestMappingHandlerMapping impl实现 MatchableHandlerMapping接口、EmbeddedValueResolverAware接口
--|RequestMappingInfoHandlerMapping
--|AbstractHandlerMethodMapping impl实现 InitializingBean接口
--|AbstractHandlerMapping impl实现 HandlerMapping接口、BeanNameAware接口、Ordered接口
--|WebApplicationObjectSupport impl实现 ServletContextAware接口
--|ApplicationObjectSupport impl实现 ApplicationContextAware接口
RequestMappingHandlerMapping 是HandlerMapping接口的实现
interface HandlerMapping {
HandlerExecutionChain gethandler (HttpServletRequest request);
}
注册bean过程:
spring 扩展机制, InitializingBean 接口 afterPropertiesSet() 方法:在类初始化完成调用此方法
AbstractHandlerMethodMapping 的 afterPropertiesSet() 方法
//等对象初始化完成调用该方法
public void afterPropertiesSet() {
initHandlerMethods();
}
/**
* 初始 HandlerMethod
* 1、获取所有Object 的 bean名称
* 2、过滤掉 scopedTarget. 的bean名称
* 3、通过bean名称得到bean类型, 储存包含@Controller @RequestMapping 注解的class
*/
protected void initHandlerMethods() {
for (String beanName : getCandidateBeanNames()) { //获取所有bean名称
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
//如果该beanName, 不是scopedTarget. 处理bean
//1、先获取该bean的class
//2、通过class去判断是否含有@Controller @RequestMapping 注解
//3、处理该class, 创建 RequestMappingInfo 对象. ====>>>> detectHandlerMethods()
//4、把该class中的方法注册到 MappingRegistry 中. ===>>>> registerHandlerMethod()
processCandidateBean(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
/**
* 确定指定的候选bean的类型,如果标识为Controller处理程序类,则调用{@link #detectHandlerMethods}。
*/
protected void processCandidateBean(String beanName) {
Class<?> beanType = null;
try {
// 获取bean名称对应的class
beanType = obtainApplicationContext().getType(beanName);
}
catch (Throwable ex) {
if (logger.isTraceEnabled()) {
logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
}
}
if (beanType != null && isHandler(beanType)) { //效验当前class是否 @Controller 类和 @RequestMapping类
// 在对该class 做处理
detectHandlerMethods(beanName);
}
}
// 是否@Controller控制类
@Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
/**
* 处理@Controller @RequestMapping 处理的类beaName
*/
protected void detectHandlerMethods(Object handler) {
Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
//是否代理class
Class<?> userType = ClassUtils.getUserClass(handlerType);
//获取类中的所有 Method ==>> RequestMappingInfo
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
// 创建 RequestMappingInfo 对象为 @RequestMapping()注解中的信息
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler", ex);
}
});
if (logger.isTraceEnabled()) {
logger.trace(formatMappings(userType, methods));
}
// 此时的mapping 键为 RequestMappingInfo
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
// 通过该方法注册调用bean的信息
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
这里看AbstractHandlerMethodMapping 类中一个属性对象 MappingRegistry (缓存池), 是一个内部类.主要用来储存对象信息.如:HandlerMethod(处理方法)、 RequestMappingInfo(请求路径)、 CorsConfiguration(跨域)
class MappingRegistry {
//储存 MappingRegistration 所有的注册信息
private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
//储存RequestMappingInfo 与 HandlerMethod
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
//储存路径与RequestMappingInfo
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();
//储存@RequestMapping 注解的请求路径 与 HandlerMethod列表
private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();
//跨域配置
private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();
//读写锁
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
/**
* 注册数据: mapping => RequestMappingInfo || handler => beanName || method => Method
* 1、创建 HandlerMethod, 根据 handle 和 method
* 2、效验 HandlerMethod 是否存在
* 3、储存 HandlerMethod
* 4、储存 RequestMappingInfo 跟 url
* 5、储存 @RequestMapping 注解 的路径跟所有的方法
* 6、存储 CorsConfiguration 信息(跨域)
* 7、储存 MappingRegistration 对象
*/
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock(); //获取写锁
try {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
assertUniqueMethodMapping(handlerMethod, mapping);
this.mappingLookup.put(mapping, handlerMethod);//注册RequestMappingInfo 和 HandlerMethod
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
this.urlLookup.add(url, mapping); //注册请求路径与对应的RequestMappingInfo
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);//注册请求路径与HandlerMethod
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);//注册HandlerMethod与跨域信息
}
//创建及注册 MappingRegistation 信息
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
//最后, 释放写锁
this.readWriteLock.writeLock().unlock();
}
}
}
spring源码地址(已翻译): https://github.com/PazzFj/spring-framework
类介绍:
HandlerMethod : 对应被@Controller 注解的类中的方法, 封装成 HandlerMethod 对象
RequestMappingInfo:对应@RequestMapping 注解中信息,保存为RequestMappingInfo 对象
版权声明:本文为baidu_36327010原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。