news 2026/4/20 17:05:18

SpringBoot源码剖析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot源码剖析

源码剖析 - 依赖管理

问题 1:为什么导入 dependency 时不需要指定版本?

在 Spring Boot 项目中,pom.xml核心依赖为spring-boot-starter-parentspring-boot-starter-web,其中spring-boot-starter-parent是版本管理的核心:

1. spring-boot-starter-parent 核心作用
<!-- Spring Boot父项目依赖管理 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>

spring-boot-starter-parent底层做了三件核心事:

  • properties 节点:定义 Java 版本(1.8)、编码(UTF-8)、Maven 编译版本等基础配置;
  • build 节点:配置资源过滤(支持多环境配置文件如application-dev.yml)、插件版本管理;
  • 继承 spring-boot-dependencies:这是真正的版本管理核心,通过dependencyManagement锁定所有 Spring Boot 组件版本。
2. spring-boot-dependencies 核心配置
<!-- 版本属性定义 --> <properties> <activemq.version>5.15.13</activemq.version> <antlr2.version>2.7.7</antlr2.version> <!-- 所有组件版本定义 --> </properties> <!-- 依赖版本管理 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot</artifactId> <version>${revision}</version> </dependency> <!-- 所有核心组件版本锁定 --> </dependencies> </dependencyManagement>

结论:项目继承spring-boot-starter-parent后,自动继承了spring-boot-dependencies的版本锁定,因此无需手动指定依赖版本。

问题 2:项目运行依赖的 JAR 包从何而来?

spring-boot-starter-web是场景化依赖启动器,核心作用是依赖传递

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>

spring-boot-starter-web内部封装了 Web 开发所需的所有底层依赖:

  • spring-boot-starter-tomcat:内置 Tomcat 服务器
  • spring-boot-starter-validation:参数校验
  • spring-web+spring-webmvc:Spring MVC 核心

结论:场景启动器通过依赖传递引入所有相关 JAR 包,版本由spring-boot-starter-parent统一管理。第三方启动器(如druid-spring-boot-starter)需手动指定版本。

源码剖析 - 自动配置

核心问题:Spring Boot 如何实现自动配置?

Spring Boot 自动配置核心是@SpringBootApplication注解,其本质是组合注解:

@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration // 标识配置类 @EnableAutoConfiguration // 核心:开启自动配置 @ComponentScan(...) // 组件扫描 public @interface SpringBootApplication { Class<?>[] exclude() default {}; // 排除自动配置类 String[] excludeName() default {}; // 排除自动配置类名 String[] scanBasePackages() default {}; // 自定义扫描包 }

1. @SpringBootConfiguration

本质是@Configuration,标识当前类为 Spring 配置类,等价于 XML 配置文件。

2. @EnableAutoConfiguration(核心)

@AutoConfigurationPackage // 自动配置包 @Import(AutoConfigurationImportSelector.class) // 导入自动配置选择器 public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
(1)@AutoConfigurationPackage

通过@Import(AutoConfigurationPackages.Registrar.class)注册当前主类所在包为自动配置基础包,用于扫描用户自定义组件。

(2)AutoConfigurationImportSelector 核心逻辑

自动配置的核心流程:

  1. 加载候选配置类:从META-INF/spring.factories读取EnableAutoConfiguration对应的自动配置类;
  2. 排除指定类:排除exclude属性指定的配置类;
  3. 条件过滤:通过@ConditionalOnClass/@ConditionalOnBean等注解过滤不符合条件的配置类;
  4. 注册有效配置类:将最终符合条件的配置类注入 IOC 容器。

3. 条件注解(@Conditional 系列)

注解

作用

@ConditionalOnBean

容器存在指定 Bean 时生效

@ConditionalOnClass

类路径存在指定类时生效

@ConditionalOnMissingBean

容器不存在指定 Bean 时生效

@ConditionalOnWebApplication

Web 环境下生效

@ConditionalOnProperty

配置文件存在指定属性时生效

4. 自动配置示例:HttpEncodingAutoConfiguration

@Configuration @EnableConfigurationProperties(HttpEncodingProperties.class) @ConditionalOnWebApplication // Web 环境生效 @ConditionalOnClass(CharacterEncodingFilter.class) // 存在字符编码过滤器 @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration { private final HttpEncodingProperties properties; @Bean @ConditionalOnMissingBean public CharacterEncodingFilter characterEncodingFilter() { // 构建过滤器并绑定配置属性 } }

自动配置核心总结

  1. 加载spring.factories中的自动配置类;
  2. 排除指定的配置类;
  3. 条件过滤(@Conditional 系列);
  4. 注册有效配置类到 IOC 容器;
  5. 通过xxxProperties绑定配置文件属性。

源码剖析 - Run 方法执行流程

Spring Boot 启动入口

@SpringBootApplication public class MyTestMVCApplication { public static void main(String[] args) { SpringApplication.run(MyTestMVCApplication.class, args); } }

1. SpringApplication 初始化

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.resourceLoader = resourceLoader; this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); this.webApplicationType = WebApplicationType.deduceFromClasspath(); // 推断应用类型 setInitializers(getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 初始化器 setListeners(getSpringFactoriesInstances(ApplicationListener.class)); // 监听器 this.mainApplicationClass = deduceMainApplicationClass(); // 推断主类 }

2. run () 方法核心流程

public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); // 1. 初始化监听器 SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { // 2. 构建环境(系统变量、配置文件等) ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); // 3. 创建应用上下文 context = createApplicationContext(); // 4. 上下文前置处理 prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 5. 刷新上下文(IOC 容器初始化核心) refreshContext(context); // 6. 上下文后置处理 afterRefresh(context, applicationArguments); stopWatch.stop(); listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } listeners.running(context); return context; }

3. 核心步骤详解

步骤

核心操作

初始化监听器

加载spring.factories

中的SpringApplicationRunListener

构建环境

加载系统环境、配置文件(application.yml/properties

创建上下文

根据应用类型(SERVLET/REACTIVE/NONE)创建对应上下文

上下文前置处理

注册主类 BeanDefinition、加载初始化器

刷新上下文

IOC 容器初始化(BeanDefinition 扫描、加载、注册)

上下文后置处理

执行自定义扩展逻辑

源码剖析 - 自定义 Starter

1. Starter 机制核心

Starter 是 Spring Boot 「约定大于配置」的体现,通过封装通用功能,实现「引入即生效」。

2. 自定义 Starter 规范

  • 命名:官方 Starter 为spring-boot-starter-xxx,自定义建议xxx-spring-boot-starter
  • 核心:自动配置类 +spring.factories配置。

3. 自定义 Starter 实战

(1)创建 Starter 工程(Maven JAR)

依赖

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>2.2.9.RELEASE</version> </dependency> </dependencies>
(2)编写配置属性类
@ConfigurationProperties(prefix = "simplebean") public class SimpleBean { private int id; private String name; // getter/setter/toString }
(3)编写自动配置类
@Configuration @ConditionalOnBean(ConfigMarker.class) // 热插拔条件 @EnableConfigurationProperties(SimpleBean.class) public class MyAutoConfiguration { static { System.out.println("MyAutoConfiguration init...."); } @Bean public SimpleBean simpleBean() { return new SimpleBean(); } }
(4)配置 spring.factories

resources/META-INF/spring.factories中添加:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.lagou.config.MyAutoConfiguration
(5)热插拔实现
  • 标记类:
public class ConfigMarker {}
  • 启用注解:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Import(ConfigMarker.class) public @interface EnableRegisterServer {}

4. 使用自定义 Starter

(1)引入依赖
<dependency> <groupId>com.lagou</groupId> <artifactId>zdy-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
(2)配置属性
simplebean.id=1 simplebean.name=自定义starter
(3)测试
@Autowired private SimpleBean simpleBean; @Test public void zdyStarterTest() { System.out.println(simpleBean); }

源码剖析 - 内嵌 Tomcat

1. 默认容器与切换

Spring Boot 引入spring-boot-starter-web后默认使用 Tomcat,切换容器只需排除 Tomcat 依赖并引入其他容器:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <artifactId>spring-boot-starter-tomcat</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency> <!-- 引入 Jetty --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>

2. 内嵌 Tomcat 自动配置原理

(1)自动配置类:ServletWebServerFactoryAutoConfiguration

spring.factories加载,通过@Import导入 Tomcat/Jetty/Undertow 自动配置类:

@Configuration @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @ConditionalOnClass(ServletRequest.class) @ConditionalOnWebApplication(type = Type.SERVLET) @Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, EmbeddedTomcat.class, EmbeddedJetty.class, EmbeddedUndertow.class }) public class ServletWebServerFactoryAutoConfiguration {}
(2)Tomcat 启动核心

TomcatServletWebServerFactorygetWebServer()方法创建并启动 Tomcat:

public WebServer getWebServer(ServletContextInitializer... initializers) { Tomcat tomcat = new Tomcat(); // 配置 Tomcat 端口、连接器等 tomcat.start(); // 启动 Tomcat return new TomcatWebServer(tomcat); }
(3)Tomcat 启动触发点

refreshContext()中调用onRefresh()->createWebServer(),最终触发getWebServer()启动 Tomcat。

源码剖析 - 自动配置 SpringMVC

1. 核心自动配置类:DispatcherServletAutoConfiguration

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) public class DispatcherServletAutoConfiguration {}

2. 自动配置核心逻辑

(1)配置 DispatcherServlet
@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServlet dispatcherServlet(HttpProperties httpProperties, WebMvcProperties webMvcProperties) { DispatcherServlet dispatcherServlet = new DispatcherServlet(); // 配置 DispatcherServlet 属性 return dispatcherServlet; }
(2)注册 DispatcherServlet 到 ServletContext

通过DispatcherServletRegistrationBean实现 Servlet 注册(Servlet 3.0 规范):

@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME) @ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet, WebMvcProperties webMvcProperties) { DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet, webMvcProperties.getServlet().getPath()); // 配置加载顺序、名称等 return registration; }

3. Servlet 注册核心流程

  1. DispatcherServletRegistrationBean继承ServletRegistrationBean
  2. 通过onStartup()调用servletContext.addServlet()注册 DispatcherServlet;
  3. 最终在 Spring Boot 启动时完成 Spring MVC 核心组件的自动注册。

核心总结

Spring Boot 自动配置 Spring MVC 的本质是:

  • 通过DispatcherServletAutoConfiguration配置 DispatcherServlet;
  • 通过 Servlet 3.0 规范的servletContext.addServlet()动态注册 DispatcherServlet;
  • 支持通过application.yml配置 Spring MVC 核心属性(如路径、加载顺序)。

关键补充

Servlet 3.0 规范支持动态注册三大组件:

  • servletContext.addServlet():注册 Servlet
  • servletContext.addFilter():注册 Filter
  • servletContext.addListener():注册 Listener

这是 Spring Boot 无需 web.xml 即可配置 Web 组件的核心原理。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 23:40:59

Tabula完整使用教程:快速从PDF提取表格数据的终极指南

Tabula完整使用教程&#xff1a;快速从PDF提取表格数据的终极指南 【免费下载链接】tabula Tabula is a tool for liberating data tables trapped inside PDF files 项目地址: https://gitcode.com/gh_mirrors/ta/tabula Tabula是一款革命性的开源工具&#xff0c;专门…

作者头像 李华
网站建设 2026/4/17 8:11:26

ANSYS Fluent完整教程:从零基础到流体动力学模拟高手

ANSYS Fluent完整教程&#xff1a;从零基础到流体动力学模拟高手 【免费下载链接】Fluent中文帮助文档1-28章完整版分享 本仓库提供了一个名为“Fluent中文帮助文档(1-28章)完整版精心整理%09包含19章、21章、24章.pdf”的资源文件下载。该文档是ANSYS Fluent的中文帮助文档&am…

作者头像 李华
网站建设 2026/4/20 15:27:35

Balena Etcher终极使用指南:轻松搞定镜像烧录

还在为系统镜像烧录烦恼吗&#xff1f;Balena Etcher这款开源神器将彻底改变您的体验&#xff01;作为一款专业的跨平台镜像写入工具&#xff0c;Etcher让复杂的系统部署变得简单直观&#xff0c;无论您是初学者还是专业人士&#xff0c;都能在几分钟内完成各种操作系统的烧录任…

作者头像 李华
网站建设 2026/4/18 10:58:05

Windows HEIC缩略图终极解决方案:告别文件预览困扰的完整指南

Windows HEIC缩略图终极解决方案&#xff1a;告别文件预览困扰的完整指南 【免费下载链接】windows-heic-thumbnails Enable Windows Explorer to display thumbnails for HEIC files 项目地址: https://gitcode.com/gh_mirrors/wi/windows-heic-thumbnails 还在为Windo…

作者头像 李华
网站建设 2026/4/17 8:41:08

神马 9.0 2025 最新版源码系统:安全加固 + 二次开发友好

采用轻量级模块化设计&#xff0c;核心功能与扩展插件彻底解耦&#xff0c;不仅安装包体积压缩了 30%&#xff0c;运行时内存占用也明显降低&#xff0c;低配服务器也能流畅承载。技术层面新增了 MySQL8.0 适配支持&#xff0c;优化了数据库索引结构&#xff0c;查询响应速度比…

作者头像 李华
网站建设 2026/4/18 19:04:45

poi-tl-ext终极指南:Java文档自动化的完整解决方案

poi-tl-ext终极指南&#xff1a;Java文档自动化的完整解决方案 【免费下载链接】poi-tl-ext Extensions for poi-tl 项目地址: https://gitcode.com/gh_mirrors/po/poi-tl-ext 还在为繁琐的Word文档生成而烦恼吗&#xff1f;poi-tl-ext作为Apache POI和poi-tl的强大扩展…

作者头像 李华