SpringBoot-MVC配置类与 Controller 的扫描

文章目录


前言

本章主要研究 SpringBoot 对于 MVC 的自动配置,本篇文章基于 springboot2.7.3

一、自动配置类位置

springboot 2.7 版本将推荐使用 org.springframework.boot.autoconfigure.AutoConfiguration.imports 这种配置,并且在 3 版本后废弃 spring.factories

二、自动配置类解析

2.1 WebMvcAutoConfiguration

当前类负责注入大量的 Bean 对象,并且还有好多个内部类,其中 EnableWebMvcConfiguration 是非常重要的一个配置类

2.1.1 EnableWebMvcConfiguration

此类继承了 DelegatingWebMvcConfiguration, 而 DelegatingWebMvcConfiguration 又继承了 WebMvcConfigurationSupport, 在 WebMvcConfigurationSupport 中注入了一个 RequestMappingHandlerMapping
RequestMappingHandlerMapping 实现了 InitializingBean 接口,所以在该类初始化的时候会调用 afterPropertiesSet(), 在该类中,该方法会扫描所有的 Controller 并解析所有的请求路径

2.2 DispatcherServletAutoConfiguration

这个自动配置类注入了 springmvc 的入口类 DispatcherServlet

三、RequestMapping 的扫描过程

从 2.1.1 可知 RequestMappingHandlerMapping 实现了InitializingBean 接口,那该类在 spring 的生命周期过程中会执行 afterPropertiesSet 方法

3.1 RequestMappingHandlerMapping#afterPropertiesSet

java 复制代码
// RequestMappingHandlerMapping#afterPropertiesSet
@Override
@SuppressWarnings("deprecation")
public void afterPropertiesSet() {
	... 
	// 调用父类的 afterPropertiesSet,也就是 AbstractHandlerMethodMapping
	super.afterPropertiesSet();
}

// AbstractHandlerMethodMapping#afterPropertiesSet
@Override
public void afterPropertiesSet() {
	initHandlerMethods();
}

3.2 RequestMappingHandlerMapping#initHandlerMethods

java 复制代码
protected void initHandlerMethods() {
	// 遍历所有的 bean
	for (String beanName : getCandidateBeanNames()) {
		if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
			// 处理符合条件的 bean
			processCandidateBean(beanName);
		}
	}
	handlerMethodsInitialized(getHandlerMethods());
}

3.3 RequestMappingHandlerMapping#processCandidateBean

java 复制代码
protected void processCandidateBean(String beanName) {
	Class<?> beanType = null;
	try {
	// 获取 bean 类型
		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);
		}
	}
	// 判断是不是 handler, 如果是获取里面的方法
	if (beanType != null && isHandler(beanType)) {
		detectHandlerMethods(beanName);
	}
}

// RequestMappingHandlerMapping#isHandler
// 判断该类上是否标注了 @Controller 或者 @RequestMapping
@Override
protected boolean isHandler(Class<?> beanType) {
	return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
			AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}

3.4 RequestMappingHandlerMapping#detectHandlerMethods

java 复制代码
protected void detectHandlerMethods(Object handler) {
	Class<?> handlerType = (handler instanceof String ?
			obtainApplicationContext().getType((String) handler) : handler.getClass());

	if (handlerType != null) {
		Class<?> userType = ClassUtils.getUserClass(handlerType);
		// 获取 HandlerMapping
		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);
					}
				});
		...
		// 注册 HandlerMethod
		// 里面的代码都很简单了
		methods.forEach((method, mapping) -> {
			Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
			registerHandlerMethod(handler, invocableMethod, mapping);
		});
	}
}


总结

提示:这里对文章进行总结:

例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

相关推荐
Moment4 小时前
长上下文会最终杀死 Rag 吗?
前端·javascript·后端
蝎子莱莱爱打怪5 小时前
🚀 🚀🚀2026年5月GitHub月榜精选:17个项目中挑出10个推荐,实操4个!
人工智能·后端·ai编程
砍材农夫6 小时前
物联网实战:Spring Boot MQTT | MQTT 设备模拟器演示(附源码)
java·spring boot·后端·物联网·spring·netty
我叫黑大帅6 小时前
解决聊天页内部滚轮改为页面滚动问题
javascript·后端·面试
YDS8296 小时前
DeepSeek RAG&MCP + Agent智能体项目 —— Agent执行链路设计之ReAct Loop
java·spring boot·ai·agent·deepseek
IT_陈寒7 小时前
Python的线程池居然把我坑在了垃圾回收这块
前端·人工智能·后端
zhangxingchao8 小时前
AI应用开发八:RAG相关技术总结
前端·人工智能·后端
吴佳浩8 小时前
Go史上最大“打脸”现场来了:泛型方法终于实现了
后端·go
Huyuejia8 小时前
runtime-ask
后端
Rust研习社8 小时前
90% 的 Rust 新手都不知道的 3 个实用开发技巧
后端·rust·编程语言