为什么要看这个方法?
正是这个方法里,完成了从 URL 到处理方法的映射。
类 AbstractHandlerMethodMapping< T >,它实现了 InitializingBean 接口,意味着肯定重写了 afterPropertiesSet 方法,跟 afterPropertiesSet
另外 AbstractHandlerMethodMapping< T > 里有一个很重要的内部类:
- urlLookup:URI 和 LinkedList< RequestMappingInfo > 的映射关系
- mappingLookup:RequestMappingInfo(@RequestMapping信息) 和 HandlerMethod(处理方法)的映射关系
5.2.1 afterPropertiesSet
Spring 启动的时候完成从 url 到方法的映射
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
跟 initHandlerMethods:
protected void initHandlerMethods() {
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
跟 processCandidateBean:
protected void processCandidateBean(String beanName) {
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.isTraceEnabled()) {
logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
}
}
//如果类上面有@Controller注解或者@RequestMapping注解
if (beanType != null && isHandler(beanType)) {
//建立uri和method的映射关系
detectHandlerMethods(beanName);
}
}
跟 detectHandlerMethods:
//被@Controller或者@RequestMapping注解的类名
protected void detectHandlerMethods(Object handler) {
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
Class<?> userType = ClassUtils.getUserClass(handlerType);
//获取方法对象和方法上面的@RequestMapping注解属性封装对象的映射关系
// T : RequestMappingInfo 5.2.1.2
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
//5.2.1.1
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
if (logger.isTraceEnabled()) {
logger.trace(formatMappings(userType, methods));
}
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
//建立uri和方法的各种映射关系,根据uri要能够找到method对象 5.2.1.3
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
5.2.1.1 getMappingForMethod
类 RequestMappingHandlerMapping
@Override
@Nullable //被@RequestMapping注解的方法 被注解的类
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
//寻找有@RequestMapping注解的方法,然后注解里面的属性封装成对象
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
//类上面的@RequestMapping注解也封装成对象
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
//把方法上面的注解属性结合到类上面的RequestMappingInfo对象中
info = typeInfo.combine(info);
}
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).build().combine(info);
}
}
return info;
}
5.2.1.2 selectMethods
public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup) {
final Map<Method, T> methodMap = new LinkedHashMap<>();
Set<Class<?>> handlerTypes = new LinkedHashSet<>();
Class<?> specificHandlerType = null;
if (!Proxy.isProxyClass(targetType)) {
specificHandlerType = ClassUtils.getUserClass(targetType);
//加上自己
handlerTypes.add(specificHandlerType);
}
//加上自己实现的接口
handlerTypes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetType));
for (Class<?> currentHandlerType : handlerTypes) {
final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);
//循环currentHandlerType类的所有方法
ReflectionUtils.doWithMethods(currentHandlerType, method -> {
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
//判断方法上面是否有@RequestMapping注解,如果有封装成RequestMappingInfo对象返回 见上面代码块的匿名方法
T result = metadataLookup.inspect(specificMethod);
if (result != null) {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {
//建立方法对象和注解封装对象的映射关系
methodMap.put(specificMethod, result);
}
}
}, ReflectionUtils.USER_DECLARED_METHODS);
}
return methodMap;
}
跟 doWithMethods:
public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) {
// Keep backing up the inheritance hierarchy.
//所有有@RequestMapping的方法
Method[] methods = getDeclaredMethods(clazz);
for (Method method : methods) {
if (mf != null && !mf.matches(method)) {
continue;
}
try {
//见上面代码块的匿名方法
mc.doWith(method);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
}
}
if (clazz.getSuperclass() != null) {
doWithMethods(clazz.getSuperclass(), mc, mf);
}
else if (clazz.isInterface()) {
for (Class<?> superIfc : clazz.getInterfaces()) {
doWithMethods(superIfc, mc, mf);
}
}
}
5.2.1.3 registerHandlerMethod
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
跟 register:
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
//创建HandlerMethod对象
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
//检验是否唯一
assertUniqueMethodMapping(handlerMethod, mapping);
//建立RequestMappingInfo和handlerMethod的映射关系
this.mappingLookup.put(mapping, handlerMethod);
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
//建立url(uri)和RequestMappingInfo映射关系
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
//判断method上是否有@CrossOrigin注解,把注解里面的属性封装成CorsConfiguration,这个是做跨域访问控制的
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();
}
}
跟 createHandlerMethod:
protected HandlerMethod createHandlerMethod(Object handler, Method method) {
HandlerMethod handlerMethod;
//如果是被注解的类名
if (handler instanceof String) {
String beanName = (String) handler;
handlerMethod = new HandlerMethod(beanName,
obtainApplicationContext().getAutowireCapableBeanFactory(), method);
}
else {
handlerMethod = new HandlerMethod(handler, method);
}
return handlerMethod;
}