关于RequestMappingHandlerMapping中初始化Controller流程
类关系图
在使用SpringMVC写Controller时,一般会使用到@Controller,@RequestMapping等注解,RequestMappingHandlerMapping在所有bean初始化完成时,将打了@Controller,@RequestMapping注解的接口生成相应的映射关系,注册到SpringMVC中。
RequestMappingHandlerMapping继承了AbstractHandlerMethodMapping抽象类,而AbstractHandlerMethodMapping又实现了InitializingBean接口,所以在RequestMappingHandlerMapping中首先会执行afterPropertiesSet()方法。
Controller
新建BaseController,写两个Method,进行分析。
@RestController
public class BaseController {
@GetMapping("test")
public String test(){
return "test api";
}
@GetMapping("name")
public String name(){
return "test api";
}
}
RequestMappingHandlerMapping
@Override
@SuppressWarnings("deprecation")
public void afterPropertiesSet() {
this.config = new RequestMappingInfo.BuilderConfiguration();
this.config.setUrlPathHelper(getUrlPathHelper());
this.config.setPathMatcher(getPathMatcher());
this.config.setSuffixPatternMatch(useSuffixPatternMatch());
this.config.setTrailingSlashMatch(useTrailingSlashMatch());
this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
this.config.setContentNegotiationManager(getContentNegotiationManager());
// 调用AbstractHandlerMethodMapping.afterPropertiesSet()
super.afterPropertiesSet();
}
// 类上有@Controller或@RequestMapping注解的,判定为controller
@Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
@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);
}
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
}
}
return info;
}
AbstractHandlerMethodMapping
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
protected void initHandlerMethods() {
// getCandidateBeanNames()获取所有的bean名称
for (String beanName : getCandidateBeanNames()) {
// 不以"scopedTarget"开头
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
// 处理候选bean
processCandidateBean(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
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);
}
}
// RequestMappingHandlerMapping.isHandler(beanType)判断是否打了@Controller或@RequestMapping
if (beanType != null && isHandler(beanType)) {
// 在指定的(beanName)bean中找到HandlerMethod
detectHandlerMethods(beanName);
}
}
protected void detectHandlerMethods(Object handler) {
// handler instanceof String==true,拿到class
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
// 找到原始类(如果是代理类就找超类)
Class<?> userType = ClassUtils.getUserClass(handlerType);
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
// 得到RequestMappingInfo对象
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));
}
// 遍历Method与RequestMappingInfo映射Map
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
// 注册HandlerMethod
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
public void register(T mapping, Object handler, Method method) {
// Assert that the handler method is not a suspending one.
if (KotlinDetector.isKotlinType(method.getDeclaringClass())) {
Class<?>[] parameterTypes = method.getParameterTypes();
if ((parameterTypes.length > 0) && "kotlin.coroutines.Continuation".equals(parameterTypes[parameterTypes.length - 1].getName())) {
throw new IllegalStateException("Unsupported suspending handler method detected: " + method);
}
}
// 加锁
this.readWriteLock.writeLock().lock();
try {
// 生成HandlerMethod
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
// 校验HandlerMethod是否已存在
validateMethodMapping(handlerMethod, mapping);
// 不存在,放进mappingLookup中,mapping就是RequestMappingInfo对象
this.mappingLookup.put(mapping, handlerMethod);
// 获取请求的url
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
// 以name接口为例 这里name=BC#name
name = getNamingStrategy().getName(handlerMethod, mapping);
// 将handlerMethod放进nameLookup中 Map<name,handlerMethod>
addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
// 放进MappingRegistry.registry中
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
// 释放锁
this.readWriteLock.writeLock().unlock();
}
}
MethodIntrospector
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);
ReflectionUtils.doWithMethods(currentHandlerType, method -> {
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
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;
}
MappingRegistry
class MappingRegistry {
private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();
private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();
private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
}