本文侧重📝记录SpringBoot3框架源码
核心注解
理解SpringBoot源码的核心注解分别是组件注册注解、条件注解、属性绑定注解,这几个注解与SpringBoot的自动装配机制息息相关!
组件注册
组件注册是将对象存储到Spring boot的IoC容器中
- @Component:将类作为组件注册到IoC容器中。
- @ComponentScan
- 扫描指定路径下需要注册到容器中的组件。
- @SpringBootApplication注解中默认将@SpringBootApplication所标注的类所在位置标注为扫描路径。
- @Bean、@Scope:通常标注在方法上,将方法返回的对象注册到ioc容器中。
- 默认是单例(singleton)
- 通常用于导入第三方组件
- 可以通过@Scope来修改容器的作用域
- singleton:单例模式(默认值),整个 Spring 容器中只创建一个 Bean 实例。
- prototype:原型模式,每次获取 Bean 时都会创建一个新的实例。
- request:每个 HTTP 请求创建一个 Bean,仅在 Web 应用中有效。
- session:每个 HTTP Session 创建一个 Bean,仅在 Web 应用中有效。
- @Import
- 通常用与将第三方组件导入到容器中
- 其他:
- 配置类组件注册注解:@Configuration、@SpringBootConfiguration。@Configuration = @Component, @SpringBootConfiguration = @Configuration + @Index
- Web开发类组件注册注解,@Controller、@Service、@Repository = @Component
- …
条件注解
@ConditionalOnXXX如果指定注解的条件成立,则触发指定行为,例子:@ConditionalOnClass, 如果类路径中存在这个类,则触发指定行为,
- 若将这个注解放在类级别,如果注解判断生效,则整个配置类生效
- 若放在方法级别,单独对这个方法进行注解判断
属性绑定
将容器中任意组件的属性值和配置文件的配置项的值进行绑定
@ConfigurationProperties、@EnableConfigurationProperties(常用于第三方组件的属性绑定,默认会把组件放到容器中)
绑定过程
- 给容器中注册组件(@Bean/@Component)
- 使用
@ConfigurationProperties声明组件和配置文件的哪些配置项进行绑定
核心原理
启动过程

- Listener从
META-INF/spring.factories读到 - 引导:利用
BootstrapContext引导整个项目启动- starting: 应用开始,只要有了
BootstrapContext就直接调用 prepareEnvironment: 配置环境变量,但是ioc还没创建
- starting: 应用开始,只要有了
- 启动:
contextPrepared: 创建ioc容器,但是sources(主配置类)还没加载。并关闭引导上下文。contextLoaded:ioc容器加载。主配置类加载进去了。但是ioc容器还没刷新(我们的bean还没创建)started: ioc容器刷新了(所有的bean还没创建),但是runner没调用。ready:ioc容器刷新了(所有的bean还没创建),而且runner调用完了。
- 运行:
- 以前步骤都正确执行,代表容器running
回调监听器
BootStrapRegistryInitializer:感知特定阶段:感知引导初始化META-INF/spring.factories- 创建引导上下文
bootstrapContext的时候触发 - 场景:进行密钥校对授权
ApplicationContextInitializer:感知特定阶段:感知ioc容器初始化ApplicationListener:感知全阶段 :基于事件机制,感知事件。SpringApplicationRunListener:感知全阶段: 各种阶段都能自定义操作ApplicationRunner:感知特定阶段:感知应用就绪Ready。卡死应用,就不会就绪。CommandLineRunner:感知特定阶段:感知应用就绪Ready。卡死应用,就不会就绪。
9大事件
ApplicationStartingEvent:应用启动但未做任何事情,除过注册listeners and initializersApplicationEnvironmentPreparedEvent:Environment准备好,但context未创建ApplicationContextInitializedEvent:ApplicationContext准备好,ApplicationContextInitializers调用,但是任何bean未加载ApplicationPreparedEvent:容器刷新之前,bean定义信息加载ApplicationStartedEvent:容器刷新完成,runner未调用AvailabilityChangeEvent(存活探针):LivenessState.CORRECT应用存活ApplicationReadyEvent:任何runner被调用AvailabilityChangeEvent(就绪探针):ReadinessState.ACCEPTING_TRAFFIC应用就绪,可以接受请求ApplicationFailedEvent:启动出错
自动配置原理
应用关注的三大核心:场景、配置、组件
自动配置原理是依赖于SPI思想
SPI(Service Provider Interface)是一种为服务提供者(Service Providers)设计的接口,它允许服务的实现与服务的使用者(Service Consumers)解耦。通过SPI,开发者可以为某个特定的接口提供实现,而应用程序可以通过标准接口来使用这些实现。SPI 是 Java 和一些其他编程环境中常用的设计模式。
自动装配完整流程
- 导入
spring-boot-starter-web- starter导入了相关场景所有的依赖:starter-json、starter-tomcat、spring-mvc
- 每个starter中引入了核心starter
spring-boot-starter - 核心starter中引入了
spring-boot-autoconfigure依赖 spring-boot-autoconfigure包含了所有场景所需要的配置- 只要这个包下的所有类都能生效,那么相当于Spring Boot官方写好的整合功能就生效
- SpringBoot默认扫描不到
spring-boot-autoconfigure下写好的所有配置类。
- 主程序:
@SpringBootApplication。@SprinBootApplication=@SpringBootConfiguration+@EnableAutoConfiguration+@ComponentScan。- SpringBoot默认只能扫描主程序所在的包及其子包,扫描不到
spring-boot-autoconfigure包中官方写好的配置类。 @EnableAutoConfiguration:SpringBoot开启自动配置的核心。@Import(AutoConfigurationImportSelector)批量给容器中导入组件。- SpringBoot启动会默认加载156(springboot3.5.0, 不同版本数量不同)。
- 这156个配置来自于
spring-boot-autoconfigure下META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件指定的。 - 项目启动的时候利用
@Import批量导入组件机制把autoconfigure包下的156个XxxAutoConfiguration类导入进来(自动配置类)。
- 虽然导入了156个自动配置类,但并不是所有自动配置类都能生效,每一个自动配置类,都有条件注解
ConditionalOnXxx,只有条件成立,才能生效。
XxxAutoConfiguration自动配置类- 给容器中使用
@Bean给容器放一堆组件。 - 每个自动配置类都可能有
@EnableConfigurationProperties(XxxProperties.class),用来把配置文件中的属性值封装到XxxProperties属性类中。 - 以Tomcat为例:把服务器的所有配置都是以server开头的封装到属性类中。
- 只需要改配置文件的值,核心组件的底层参数都能修改
- 给容器中使用
- 业务开发
功能开关
- 自动配置:全部都配置好,什么都不用管
- 手动配置:
@EnableXxxx手动控制那些功能启动,都是利用@Import把对应功能导入进来
自定义starter流程
- 创建
自定义starter项目,引入spring-boot-starter依赖 - 编写starter功能代码,引入相关依赖
- 实现自动装配
- 编写
XxxAutoConfiguration自动配置类,帮其他项目导入这个模块需要的所有组件 @EnableXxx(可选):模仿@EnableWebMvc写@EnableXxx,可实现通过在启动类上加上这个注解就能实现自动装配- 全自动方式(可选):编写配置文件
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
- 编写
- 其他项目引入即可
Web篇
默认配置
- 包含了
ContentNegotiatingViewResolver和BeanNameViewResolve组件,用于视图解析。 - 默认进行了静态资源处理机制:静态资源在static文件夹下即可直接访问。
- 自动注册了
Converter、GenericConverter、Formatter组件,适配常见的数据类型转换和格式化需求。 - 支持
HttpMessageConverters,方便json类型数据。 - 注册
MessageCodesResolver,方便国际化及错误消息处理。 - 支持静态
index.html - 自动使用
ConfigurableWebBindingInitializer,实现消息处理,数据绑定、类型转换等功能。
‼️重要
- 如果要保持boot mvc的默认配置,并且自定义更多的mvc配置,如:interceptors、formatters、view controller等。可以使用
@Configuration注解添加一个WebMvcConfigure类型的配置类,并不要标注@EnableWebMvc。 - 如果想要保持boot mvc的配置,但要自定义核心组件实例,比如:
RequestMappinghHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver,给容器中放一个WebMvcRegistrations组件即可。 - 如果想全面接管Spring MVC,
@Configuration标注一个配置类,并加上@EnableWebMvc注解,实现WebMvcConfigurer接口。
这部分自定义配置的原理
- WebMvcAutoConfiguration是一个自动配置类,里面有一个
EnableWebMvcConfiguration EnableWebMvcConfiguration继承与DelegatingWebMvcConfiguration,这两个都生效DelegatingWebMvcConfiguration利用依赖注入获取容器中所有的WebMvcConfiguration- 别人调用
DelegatingWebMvcConfiguration的方法配置底层方法,而它调用所有WebMvcCoinfiguration的配置底层方法
原理
WebMvcAutoConfiguration原理
- 放了两个过滤器:
HiddenHttpMethodFilter: 页面表单提交REST请求(GET、POST、PUT、DELETE…)。FormContentFilter: 表单内容过滤器,一版来说GET(url)、POST(请求体)请求可以携带数据,PUT、DELETE的请求体数据会被忽略数据。
- 给容器中放了`WebMvcAutoConfigurationAdapter组件.
- 该组件实现了
WebConfig;给SpringMVC添加各种定制功能. - 这个组件绑定了两个Properties.
- WebMvcProperties:
spring.mvc - WebProperties:
spring.web
- WebMvcProperties:
- 该组件实现了
WebMvcConfigure接口- configurePathMatch: 配置路径匹配
- configureContentNegotiation: 配置内容协商
- configureAsyncSupport: 配置异步支持,处理异步请求
- configureDefaultServletHandling: 配置默认处理,默认接收:/
- addFormatters: 添加格式化器
- addInterceptors: 添加拦截器
- addResourceHandlers: 添加资源处理器,用于处理静态资源
- addCorsMappings: 添加跨域
- addViewControllers: 添加视图控制器,如令/a直接跳转到xxx.html
- configureViewResolvers: 配置视图解析
- addArgumentResolvers: 添加参数解析器
- addReturnValueHandlers: 添加返回值处理器,跳转页面/返回数据
- configureMessageConverters: 配置消息转换器
- extendMessageConverters: 扩展消息转换器
- configureHandlerExceptionResolvers: 配置异常解析器
- extendHandlerExceptionResolvers: 扩展异常解析起
- addErrorResponseInterceptors: 添加错误响应拦截器
静态资源
WebMvcAutoConfigurationAdapter中addResourceHandlers源码
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
addResourceHandler(registry, this.mvcProperties.getWebjarsPathPattern(),
"classpath:/META-INF/resources/webjars/");
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION);
registration.addResourceLocations(resource);
}
});
}
- 规则一:访问:
/webjars/**路径就去classpath:/META-INF/resources/webjars下找资源。 - 规则二:访问:
/**路径就去静态资源默认的四个位置找资源:classpath:/META-INF/resources/、classpath:/resources/、classpath:/static/、classpath:/public/ - 规则三:静态资源默认都有缓存规则的设置,如果浏览器访问了一个静态资源
index.js,如果服务器这个资源没有发生变化,下次访问的时候就可以直接让浏览器用自己缓存中的东西,而不用给服务器发请求。- 所有缓存的设置,直接通过配置文件:
spring.web - cachePeriod: 缓存周期,多久不用找服务器要新的。默认没有,以s为单位
- cacheControl: HTTP缓存控制
- userLastModified: 是否使用最后一次修改,配合HTTP Cache规则
- 所有缓存的设置,直接通过配置文件:
自定义 - 配置方式
spring.mvc: 静态资源访问前缀路径
spring.web:
- 静态资源目录
- 静态资源缓存策略
自定义 - 代码方式
容器中只要有一个WebMvcConfigure组件。配置的底层行为都会生效
@EnableWebMvc //禁用boot的默认配置
@Configuration
public class MyConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
WebMvcConfigurer.super.addResourceHandlers(registry);
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCacheControl(CacheControl.maxAge(7200, TimeUnit.SECONDS));
}
}
路径匹配
Spring5.3之后加入了更多的请求路径匹配的实现策略:
PathPatternParser以前只支持
AntPathMatcher默认使用新版的匹配路径,可以配置spring.mvc.pathmatch.matching-strategy来修改匹配策略
两者区别
PathPatternParser在jmh基准测试下,有6~8倍吞吐量提升,降低30%~40%空间分配率PathPatternParser兼容AntPathMatcher语法,并支持更多类型的路径模式PathPatternParser中**多目录匹配的支持仅运行在模式末尾使用
内容协商
一套系统适配多端数据返回
HttpMessageConverter原理
@ResponseBody由HttpMessageConverter处理- 若有类被
@ResponseBody标注- 请求先经过
DispatcherServlet的doDispatch()进行处理 - 找到一个
HandlerAdapter适配器,利用适配器执行目标方法 RequestMappingHandlerAdapter来执行,调用invokeHandlerMethod()来执行方法- 目标方法执行前,准备好两个东西
HandlerMethodArgumentResolver:参数解析器,确定目标方法的每个参数值HandlerMethodReturnValueHandler:返回值解析器,确定目标方法的返回值怎么处理
RequestMappingHandlerAdapter里面的invokeAndHandle()真正执行目标方法- 目标方法执行完成,会返回返回值对象
- 找到一个合适的返回值处理
HandlerMethodReturnValueHandler,即RequestResponseBodyMethodProcessor RequestResponseBodyMethodProcessor利用writeWithMessageConverters把返回值写出去
- 请求先经过
HttpMessageConverter会先进行内容协商- 遍历所有的
HttpMessageConverter看谁支持这种内容类型的数据 - 最终因为要
json所以使用MappingJackson2HttpMessageConverter jackson用ObjectMapper把对象写出去
- 遍历所有的
- 若有类被
WebAutoConfiguration提供的默认HttpMessageConverters- ByteArrayHttpMessageConverter:字节数据读写
- StringHttpMessageConverter:字符串读写
- ResourceHttpMessageConverter:资源读写
- ResourceRegionHttpMessageConverter:分区资源读写
- AllEncompassingFormHttpMessageConverter:表单读写
- MappingJackson2HttpMessageConverter:请求响应体Json读写
- MappingJackson2XmlHttpMessageConverter:请求响应体Xml读写
异常处理
错误处理的自动配置都在
ErrorMvcAutoConfiguration中,两大核心
- SpringBoot会自适应处理错误,响应页面或JSON数据
- Spring MVC的错误处理机制依然保留,MVC处理不了,才会交给Boot进行处理
原理
SpringBoot中的异常处理首先会依次经过@ExceptionHandler标注的方法、@ResponseStatus标注的方法、@SpringMVC定义的默认错误响应处理方法进行处理,若不能处理则跳转至
/error页面,而/error页面是由BasicErrorController进行处理的。BasicErrorController中errorHTML会处理异常跳转的逻辑@RequestMapping(produces = MediaType.TEXT_HTML_VALUE) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections .unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView != null) ? modelAndView : new ModelAndView("error", model); }首先他会从容器中找到能够处理该错误状态(304、404)的视图页面
@Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) { ModelAndView modelAndView = resolve(String.valueOf(status.value()), model); if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) { modelAndView = resolve(SERIES_VIEWS.get(status.series()), model); } return modelAndView; }- 如果发生了304、404等错误,默认在classpath:/templates/error/状态码.html
- 如果没有对应的视图页面,在静态资源文件夹下找
状态码.html - 如果无法匹配精确的状态码的页面,则模糊找
5xx.html、4xx.html, - 如果没有对应的视图页面,在静态资源文件夹下找
5xx.html、4xx.html
若没有能处理的,则跳转到/error页面
自定义错误响应
- 前后端分离
- 后台发生的所有错误,
@ControllerAdvice + @ExceptionHandler进行统一异常处理
- 后台发生的所有错误,
- 服务端渲染
- 给
classpath:/templates/error/下放错误页面: 500.html、5xx.html。。。
- 给
- 发生业务错误
- 核心业务,每一种错误,都应该代码控制,跳转到自己定制的错误页
- 通用业务,
classpath:/templates/error.html页面,显示错误信息
Web嵌入式容器
管理、运行Servlet组件(Servlet、Filter、Listener)的环境,一般指服务器
原理
ServletWebServerFactoryAutoConfiguration自动配置了容器场景,绑定了ServerProperties,配置了嵌入式三大服务器(Tomcat、Jettty、Undertow)通过条件注解,来确定使哪个嵌入式服务器生效
每个服务器都有
ServletWebServerFactory,每个Web服务器工厂都有getWebServer方法来获取web服务器ServletWebServerApplicationContextioc容器启动时会调用创建web服务器createWebServer(),而createWebServer()会调用getWebServer()方法Spring容器刷新(启动)的时候,会预留一个时机,刷新子容器。
onRefresh(),而容器刷新的时候会调用createWebServer()方法@Override protected void onRefresh() { super.onRefresh(); try { createWebServer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start web server", ex); } }Refresh容器刷新经典12大步的刷新子容器会调用onRefresh
Spring Boot中的SpringMVC
原理
WebMvcAutoConfigurationweb自动配置类分析
Spring MVC自动配置场景配置了如下所有场景
OrderedHiddenHttpMethodFilter:支持RESTful的filterOrderedFormContentFilter:支持非POST请求,请求提携带数据WebMvcAutoConfigurationAdapter配置生效,它是一个WebMvcConfigurer,定义mvc底层组件- 定义好
WebMvcConfigurer底层组件默认功能 InternalResourceViewResolver、BeanNameViewResolver:视图解析器ContentNegotiatingViewResolver:内容协商解析器RequestContextFilter:请求上下文的过滤器, 使得请求在任意位置都可以获取当前请求
- 定义好
EnableWebMvcConfigurationRequestMappingHandlerAdapterWelcomePageHandlerMapping:欢迎页功能支持(模板引擎目录、静态资源目录)LocaleResolver:国际化解析器ThemeResolver:主题解析器(已弃用)FlashMapManager:临时数据解析器FormattingConversionService:数据格式化、类型转换Validator:数据校验’JSR’提供的数据校验功能WebBindingInitializer:请求参数的封装与绑定RequestMappingHandlerMapping:处理请求的映射关系ExceptionHandlerExceptionResolver:默认的异常解析器ContentNegotiationManager:内容协商管理器
ResourceChainResourceHandlerRegistrationCustomizer:静态资源链规则ProblemDetailsErrorHandlingConfiguration:错误详情,捕获SpringMVC内部常见异常
@EnableWebMvc会禁用WebMvcAutoConfiguration配置的信息
给容器导入了
DelegatingWebMvcConfiguration,他是WebMvcConfigurationSupport而
WebMvcAutoConfiguration中有条件注解@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)因此
@EnableWebMvc标注的注解,导入了WebMvcConfigurationSupport,使得WebMvcAutoConfiguration失效
数据访问
jdbc场景的自动配置
配置了数据源等基本信息
mybatis-spring-boot-starter导入了spring-boot-starter-jdbc,jdbc是操作数据库的场景- JDBC场景中的自动配置
DataSourceAutoConfiguration:数据源的自动配置。默认使用HikariDataSourceJdbcTemplateAutoConfiguration: 给容器中放了JdbcTemplateJndiDataSourceAutoConfiguration:允许数据源使用JNDI的方式进行连接XADataSourceAutoConfiguration:基于XA二阶段提交协议的分布式事务数据源DataSourceTransactionManagerAutoConfiguration:支持事务
mybatis场景的自动配置
mybatis-spring-boot-starter默认加载两个自动配置类MybatisLanguageDriverAutoConfiguration,语言驱动MybatisAutoConfiguration- 必须在数据源配置好之后进行配置
SqlSessionFactory:通过工厂创建SqlSession,即数据库的操作绘画SqlSessionTemplate:操作数据库的工具
- MapperScan原理:利用
@Import注解导入MapperScannerRegistrar类registerBeanDefinitions()解析指定包路径里面的每一个类,为每一个Mapper接口类,创建Bean定义信息,注册到容器