当前位置: 首页 > news >正文

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 组件的核心原理。

http://www.jsqmd.com/news/76556/

相关文章:

  • 2025年优质的无花板风管加工/角钢风管加工厂家最新热销排行 - 品牌宣传支持者
  • 2025年优秀的自动喷砂机/间歇式自动喷砂机用户口碑最好的厂家榜 - 品牌宣传支持者
  • zz【大模型】Qwen, DeepSeek, GLM的API接口调用(官方示例+LangChain示例)
  • HarmonyOS应用开发终极指南:module.json5配置完全解析与实战
  • CREST分子构象采样工具:快速上手终极指南
  • PennyLane量子机器学习实战指南:从基础到高级应用的完整教程
  • Kickstarter Android开源项目:从零开始的完整入门指南
  • RustFS监控告警终极指南:快速构建企业级存储运维体系
  • 突破材料科学瓶颈:DREAM3D 3D微结构分析软件实战指南
  • 从“对话框”到“面对面”:魔珐星云3D数字人开发实战指南
  • 48tools:多平台视频下载与直播录制工具集
  • Tabula完整使用教程:快速从PDF提取表格数据的终极指南
  • Linux随记(二十六)
  • Wan2.2-T2V-A14B在高端广告生成平台中的应用实践
  • 异步校验工具 awaitility
  • Wan2.2-T2V-A14B与知识图谱结合实现智能剧情推荐系统构想
  • CAD2020许可证验证超时问题深度解决方案
  • Llama-Factory能否用于代码生成模型微调?实测结果
  • 关于网络协议
  • 安卓离线语音识别实战:Vosk语音引擎开发全攻略
  • MultiHighlight完整指南:让代码阅读从此变得简单高效
  • 遥感图像变化检测终极指南:Open-CD快速上手与实战应用
  • 如何快速解决OpenVLA模型微调后推理中的动作归一化问题
  • 模型版本管理实战:让每一次语音实验都能精准复现
  • AI办公神器:5大开源工具颠覆效率
  • 亲测有效!DC-DC 电源啸叫不用慌
  • RustFS监控告警系统:从配置到实战的完整指南
  • 从“要不要”到“如何好”:解码数字化转型的核心逻辑
  • 12月12日工作周报
  • KeyCastr终极按键可视化工具使用指南