SpringMVC何時載入的controller裡的mapping方法

CBeann發表於2020-10-09

疑問

其實我一直有一個疑問,因為我在跟自己寫的controller的生命週期原始碼的時候,沒有發現解析mapping的程式碼,然後我就在想,什麼時候解析並載入的mapping呢???

結果是一個新的類   RequestMappingHandlerMapping  ,驚呆了,我的小夥伴

demo下載

https://github.com/cbeann/Demooo/tree/master/springmvc-demo-app

原始碼跟進

我就從RequestMappingHandlerMapping的生命週期的afterPropertiesSet()方法講起

//RequestMappingHandlerMapping
@Override
	public void afterPropertiesSet() {
		this.config = new RequestMappingInfo.BuilderConfiguration();
		this.config.setUrlPathHelper(getUrlPathHelper());
		this.config.setPathMatcher(getPathMatcher());
		this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);
		this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);
		this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);
		this.config.setContentNegotiationManager(getContentNegotiationManager());
        //呼叫父類的方法,跟進去--->
		super.afterPropertiesSet();
	}
//AbstractHandlerMethodMapping
protected void initHandlerMethods() {
        //遍歷所有的類
		for (String beanName : getCandidateBeanNames()) {
			if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
                //當beanName為自定義的helloController時跟進去--->
				processCandidateBean(beanName);
			}
		}
		handlerMethodsInitialized(getHandlerMethods());
	}

 

 

//AbstractHandlerMethodMapping
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)) {
            //跟進去--->
			detectHandlerMethods(beanName);
		}
AbstractHandlerMethodMapping
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的方法
			Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
					(MethodIntrospector.MetadataLookup<T>) method -> {
						try {
							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和mapping都注入到某個地方(map)中,後面就可以直接使用了
			methods.forEach((method, mapping) -> {
				Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
				registerHandlerMethod(handler, invocableMethod, mapping);
			});
		}
	}

此時就已經明白了,並不是在自定義的controller類的生命週期內解析的mapping,而是在RequestMappingHandlerMapping  生命週期的afterPropertiesSet()方法中獲取所有的controller類並解析

 

 

相關文章