SpringBoot核心原理:自动配置、starter、SPI机制

SpringBoot核心原理:自动配置、starter、SPI机制

SpringBoot就像一个贴心管家,你想要什么它提前帮你摆好,不用你操心配置。但管家是怎么知道你想要什么的?这篇就拆开它的脑袋看看。

一、SpringBoot vs 传统Spring

传统Spring项目有多折磨人?一堆XML配置文件,配个数据源能写半屏XML,漏个分号项目就启动不了。

SpringBoot的三个核心改变:

  1. 约定大于配置: sensible defaults,你不配就用默认值
  2. 内嵌Tomcat :不需要单独部署war包,java -jar 直接跑
  3. 零XML配置:用注解和Java配置类替代XML

一句话总结:SpringBoot不是新框架,它是Spring的"全家桶套餐+自动安装服务"。

二、起步依赖(starter)原理

2.1 starter是什么

starter是SpringBoot提供的一组依赖打包方案 。比如你引入 spring-boot-starter-web

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

一个依赖进来,背后实际上带了一大堆东西:

包含的依赖 作用
spring-web Spring MVC核心
spring-webmvc MVC框架
tomcat-embed-core 内嵌Tomcat
jackson-databind JSON序列化
spring-boot-starter-validation 参数校验

2.2 依赖传递机制

Maven的依赖传递 (transitive dependency)是starter能工作的底层机制。A依赖B,B依赖C,A自动获得C。所以你只写一行 <dependency>,Maven帮你把整棵依赖树拉进来。

这就是为什么SpringBoot项目的pom.xml看起来特别干净------复杂度被starter封装掉了。

三、自动配置核心原理

这是SpringBoot的灵魂所在。

3.1 @SpringBootApplication注解拆解

启动类上的 @SpringBootApplication 是个复合注解,拆开看:

java 复制代码
@SpringBootConfiguration   // 本质是@Configuration,标记配置类
@EnableAutoConfiguration   // 自动配置的开关
@ComponentScan             // 组件扫描,扫描当前包及子包
public class MyApplication { ... }

核心是 @EnableAutoConfiguration

3.2 从注解到AutoConfiguration.imports

@EnableAutoConfiguration 通过 @Import(AutoConfigurationImportSelector.class) 引入了一个选择器,这个选择器做的事情是:

  1. 读取 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件
  2. 把里面列出的所有自动配置类加载进来

SpringBoot 3.x之前用的是 META-INF/spring.factories,3.x之后改成了 AutoConfiguration.imports 文件,目的更清晰------把自动配置类和普通SPI配置分开。

文件内容长这样:

python 复制代码
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration
... (几百个)

3.3 条件装配注解

光加载配置类还不够,如果项目里没引Redis依赖,RedisAutoConfiguration加载了也白搭。所以每个配置类上都有一堆条件注解:

注解 条件
@ConditionalOnClass classpath存在指定类时才生效
@ConditionalOnBean 容器中存在指定Bean时才生效
@ConditionalOnProperty 配置文件中存在指定属性时才生效
@ConditionalOnMissingBean 容器中不存在指定Bean时才生效(让你能覆盖默认配置)
@ConditionalOnWebApplication 是Web应用时才生效

举例:

java 复制代码
@AutoConfiguration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisAutoConfiguration {
    // 只有classpath有Redis相关类,这个配置类才会生效
}

3.4 自动配置执行流程

scss 复制代码
启动main方法
  → 创建SpringApplication
    → refreshContext() 刷新容器
      → invokeBeanFactoryPostProcessors()
        → AutoConfigurationImportSelector执行
          → 读取AutoConfiguration.imports
            → 加载所有自动配置类
              → 逐个进行@Conditional条件判断
                → 条件满足 → 注册Bean到容器
                → 条件不满足 → 跳过

四、SPI机制简介

4.1 什么是SPI

SPI(Service Provider Interface)是一种服务发现机制。核心思想:定义接口在API包中,实现在各个SPI包中,运行时动态发现并加载实现。

4.2 Java SPI vs SpringBoot SPI

对比项 Java SPI SpringBoot SPI
配置文件位置 META-INF/services/ META-INF/spring/
配置文件名 接口全限定名 AutoConfiguration.imports
加载机制 ServiceLoader AutoConfigurationImportSelector
是否支持条件过滤 否,全部加载 是,通过@Conditional

Java SPI的缺点是"一刀切全加载",SpringBoot在此基础上加了条件判断,只加载需要的,这就是进步。

五、实战:自定义一个starter

光说不练假把式,我们来手写一个简单的starter。

5.1 项目结构

bash 复制代码
hello-spring-boot-starter/          # starter模块(空jar,只做依赖声明)
└── pom.xml

hello-spring-boot-autoconfigure/    # 自动配置模块
├── src/main/java/com/example/hello/
│   ├── HelloProperties.java        # 配置属性绑定类
│   ├── HelloService.java           # 核心服务类
│   └── HelloAutoConfiguration.java # 自动配置类
└── src/main/resources/
    └── META-INF/spring/
        └── org.springframework.boot.autoconfigure.AutoConfiguration.imports

5.2 核心代码

配置属性类:

java 复制代码
@ConfigurationProperties(prefix = "hello")
public class HelloProperties {
    private String name = "World";
    private int times = 1;
    // getter/setter省略
}

服务类:

java 复制代码
public class HelloService {
    private HelloProperties properties;

    public String sayHello() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < properties.getTimes(); i++) {
            sb.append("Hello, ").append(properties.getName()).append("!\n");
        }
        return sb.toString();
    }
    // setter省略
}

自动配置类:

java 复制代码
@AutoConfiguration
@ConditionalOnProperty(prefix = "hello", name = "enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(HelloProperties.class)
public class HelloAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public HelloService helloService(HelloProperties properties) {
        HelloService service = new HelloService();
        service.setProperties(properties);
        return service;
    }
}

AutoConfiguration.imports文件内容:

复制代码
com.example.hello.HelloAutoConfiguration

5.3 使用方式

别的项目引入这个starter后,直接注入就能用:

java 复制代码
@RestController
public class TestController {
    @Autowired
    private HelloService helloService;

    @GetMapping("/hello")
    public String hello() {
        return helloService.sayHello();
    }
}

application.yml 中配置参数:

yaml 复制代码
hello:
  name: 黑漂技术佬
  times: 3

启动项目访问 /hello,就能看到效果了。

这就是SpringBoot自动配置的完整闭环:starter声明依赖 → AutoConfiguration.imports注册配置类 → @Conditional条件判断 → @EnableConfigurationProperties绑定参数 → 注册Bean → 业务代码直接注入使用

相关推荐
阿拉斯攀登1 小时前
Web核心开发:拦截器、过滤器、跨域、统一返回
架构
dsyuan0011 小时前
基于 Vue3 + ElementPlus 极简搭建仿钉钉流程设计器,简洁架构、极易扩展,纯div+css布局
css·架构·钉钉
隔窗听雨眠2 小时前
无辅助损失函数的负载均衡:DeepSeek MoE架构的核心突破
运维·架构·负载均衡
ZGIAI11 小时前
ZGI 让那些"等你去处理"的事,真正跑起来
人工智能·架构
ZGIAI11 小时前
ZGI:别再做Agent Demo了,先问问它在业务里能不能撑过下周三
人工智能·架构
黑马程序员毕设15 小时前
基于Java的医院药品管理系统的优化设计与实现
java·开发语言·spring boot·小程序·架构·课程设计·毕设
头茬韭菜15 小时前
第 01 篇:「架构鸟瞰与进程启动链路」—— JobManager / TaskManager 从零长出来的完整调用链
架构·flink
CaseyWei15 小时前
Harness 架构 Multi‑Agent(多智能体)完整深度解析
人工智能·ai·架构·harness
源代码•宸17 小时前
前置准备:定时微服务背景和现状
开发语言·经验分享·后端·微服务·云原生·架构·golang