您的位置:首页 > 移动开发

springMVC源码分析--AbstractHandlerMethodMapping注册url和HandlerMethod对应关系(十一)

2016-12-21 18:49 627 查看
在上一篇博客springMVC源码分析--AbstractHandlerMethodMapping获取url和HandlerMethod对应关系(十)中我们简单地介绍了获取url和HandlerMethod的过程,接下来我介绍一些url和HandlerMethod对应关系的注册过程。

在AbstractHandlerMethodMapping中当bean被注入到容器后会执行一系列的初始化过程,代码如下:
//容器启动时会运行此方法,完成handlerMethod的注册操作
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}进行HandlerMethod的注册操作,简单来说就是从springMVC的容器中获取所有的beanName,注册url和实现方法HandlerMethod的对应关系。
//handlerMethod的注册操作
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}
//从springMVC容器中获取所有的beanName
String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));
//注册从容器中获取的beanName
for (String name : beanNames) {
if (!name.startsWith(SCOPED_TARGET_NAME_PREFIX) && isHandler(getApplicationContext().getType(name))) {
detectHandlerMethods(name);
}
}
handlerMethodsInitialized(getHandlerMethods());
}根据beanName进行一系列的注册,最终实现是在registerHandlerMethod
protected void detectHandlerMethods(final Object handler) {
//获取bean实例
Class<?> handlerType =
(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass());

// Avoid repeated calls to getMappingForMethod which would rebuild RequestMappingInfo instances
final Map<Method, T> mappings = new IdentityHashMap<Method, T>();
final Class<?> userType = ClassUtils.getUserClass(handlerType);

Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
@Override
public boolean matches(Method method) {
//创建RequestMappingInfo
T mapping = getMappingForMethod(method, userType);
if (mapping != null) {
mappings.put(method, mapping);
return true;
}
else {
return false;
}
}
});

for (Method method : methods) {
registerHandlerMethod(handler, method, mappings.get(method));
}
}registerHandlerMethod的注册操作是将beanName,Method及创建的RequestMappingInfo之间的 关系。
//注册beanName和method及RequestMappingInfo之间的关系,RequestMappingInfo会保存url信息
@Deprecated
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
getMappingForMethod方法是在子类RequestMappingHandlerMapping中实现的,具体实现就是创建一个RequestMappingInfo
@Override
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 RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
RequestCondition<?> condition = (element instanceof Class<?> ?
getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}

这样就简单实现了将url和HandlerMethod的对应关系注册到mappingRegistry中。
MappingRegistry中的注册实现如下,并且MappingRegistry定义了几个map结构,用来存储注册信息
private final Map<T, MappingRegistration<T>> registry = new HashMap<T, MappingRegistration<T>>();

private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<T, HandlerMethod>();

private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<String, T>();

private final Map<String, List<HandlerMethod>> nameLookup =
new ConcurrentHashMap<String, List<HandlerMethod>>();

private final Map<HandlerMethod, CorsConfiguration> corsLookup =
new ConcurrentHashMap<HandlerMethod, CorsConfiguration>();

完成beanName,HandlerMethod及RequestMappingInfo之间的对应关系注册。//注册beanName和method及RequestMappingInfo之间的关系,RequestMappingInfo中有url信息
public void register(T mapping, Object handler, Method method) {

this.readWriteLock.writeLock().lock();
try {
//创建HandlerMethod
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
assertUniqueMethodMapping(handlerMethod, mapping);

if (logger.isInfoEnabled()) {
logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
}
//保存url和handlerMethod之间的对应关系
this.mappingLookup.put(mapping, handlerMethod);
//保存url和RequestMappingInfo对应关系
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<T>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: