关于RequestMappingHandlerMapping中初始化Controller流程

关于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();
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值