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提供了大量能使我们快速便捷地处理数据的函数和方法。

相关推荐
程序员爱钓鱼1 分钟前
Go语言实战案例-创建模型并自动迁移
后端·google·go
javachen__7 分钟前
SpringBoot整合P6Spy实现全链路SQL监控
spring boot·后端·sql
uzong6 小时前
技术故障复盘模版
后端
GetcharZp6 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
桦说编程6 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研6 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi7 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
一只爱撸猫的程序猿7 小时前
使用Spring AI配合MCP(Model Context Protocol)构建一个"智能代码审查助手"
spring boot·aigc·ai编程
甄超锋8 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
阿华的代码王国8 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端