Spring Boot 概述

Spring Boot

Spring Boot 是一个基于 Java 的开源应用框架,旨在简化 Spring 应用的初始搭建和开发过程。它由 Pivotal 团队提供,核心设计思想是"约定优于配置",通过提供开箱即用的默认配置,让开发者能更专注于业务逻辑的实现,而无需编写大量样板化的配置文件。

特性

  • 自动配置 (Auto Configuration)
    这是 Spring Boot 的灵魂。它能根据项目类路径中的依赖,自动配置 Spring 应用程序。例如,当项目中引入了数据库相关的库,Spring Boot 就会自动尝试配置数据源,极大地减少了手动配置的工作量。
  • 内嵌服务器 (Embedded Server)
    Spring Boot 内置了 Tomcat、Jetty 或 Undertow 等 Web 服务器。这意味着你无需将应用打包成 WAR 文件并部署到外部的服务器中,而是可以直接打包成一个可执行的 JAR 文件,通过 java -jar 命令即可启动应用,简化了部署流程。
  • 起步依赖 (Starter Dependencies)
    Spring Boot 提供了一系列名为 "Starter" 的依赖描述符。这些 Starter 将常用功能所需的依赖整合在一起,开发者只需引入一个 Starter(如 spring-boot-starter-web),即可快速为项目添加 Web 开发能力,无需手动管理众多库的版本和兼容性。
  • 生产就绪 (Production-Ready)
    框架内置了如健康检查、指标监控、外部化配置等生产环境所需的功能(通过 spring-boot-starter-actuator 模块实现),方便对应用进行管理和监控。
  • 零代码生成与无XML配置
    Spring Boot 绝对没有代码生成,也完全不要求使用 XML 进行配置。它主要依靠注解和属性文件(如 application.yml)来完成配置,使开发体验更加现代化和简洁。

自动配置 (Auto Configuration)原理

自动配置的旅程始于我们熟悉的 @SpringBootApplication 注解。它是一个组合注解,其中真正开启自动配置的是 @EnableAutoConfiguration

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@ComponentScan(excludeFilters = { ... })
// 核心在这里:导入了自动配置的选择器
@EnableAutoConfiguration
public @interface SpringBootApplication { ... }

@EnableAutoConfiguration 注解本身通过 @Import 导入了一个至关重要的类:AutoConfigurationImportSelector

java 复制代码
@AutoConfigurationPackage
// 关键:导入 AutoConfigurationImportSelector,它是自动配置的执行核心
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration { ... }

当 Spring 容器启动并处理到这个注解时,就会触发 AutoConfigurationImportSelector 的逻辑。

加载候选配置:AutoConfigurationImportSelector

AutoConfigurationImportSelector 实现了 DeferredImportSelector 接口,其核心方法是 selectImports。这个方法负责返回所有需要导入到 Spring 容器中的配置类的全限定名。

  1. ImportSelector (立即执行)
    当一个配置类通过 @Import 导入了一个实现 ImportSelector 接口的类时,Spring 会在解析该配置类的过程中,立即调用 selectImports 方法。这意味着它的执行时机较早,发生在处理当前配置类的 @Bean@ImportResource 等其他注解之前。
  2. DeferredImportSelector (延迟执行)
    DeferredImportSelectorImportSelector 的子接口。当一个配置类导入的是 DeferredImportSelector 的实现类时,Spring 会采取延迟处理 的策略。selectImports 方法不会立即执行,而是被推迟到所有 普通的 @Configuration 配置类都被解析完成之后,才会被统一调用。
1. 获取自动配置条目 (getAutoConfigurationEntry)

selectImports 方法内部调用了 getAutoConfigurationEntry,这是整个流程的调度中心。我们可以从源码中清晰地看到它的四个核心步骤:

java 复制代码
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata metadata) {
    // 1. 加载所有候选的自动配置类
    List<String> configurations = getCandidateConfigurations(metadata, attributes);
    
    // 2. 去除重复的配置类
    configurations = removeDuplicates(configurations);
    
    // 3. 应用排除规则,例如通过 @EnableAutoConfiguration(exclude=...) 手动排除
    Set<String> exclusions = getExclusions(metadata, attributes);
    configurations.removeAll(exclusions);
    
    // 4. 【最关键一步】应用条件注解进行过滤,只保留当前环境需要的配置
    configurations = getConfigurationClassFilter().filter(configurations);
    
    // ... 发布事件等后续操作
    return new AutoConfigurationEntry(configurations, exclusions);
}
2. 读取配置清单 (getCandidateConfigurations)

getCandidateConfigurations 方法负责从固定的资源文件中加载所有候选的自动配置类。这正是"约定优于配置"的体现,Spring Boot 约定了这些配置类存放的位置。

java 复制代码
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    // 核心:使用 SpringFactoriesLoader 从 classpath 下的特定文件中加载配置类名称
    // 在 Spring Boot 2.7+ / 3.x 中,文件路径为 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
        getSpringFactoriesLoaderFactoryClass(), // 即 EnableAutoConfiguration.class
        getBeanClassLoader()
    );
    // ... 校验逻辑
    return configurations;
}

这个文件(AutoConfiguration.imports 或旧版的 spring.factories)就像一个"菜单",列出了 Spring Boot 提供的所有自动配置类,例如 DataSourceAutoConfigurationWebMvcAutoConfiguration 等。

智能筛选:条件注解 (@Conditional)

加载了成百上千个候选配置类后,Spring Boot 并不会全部启用。getConfigurationClassFilter().filter(configurations) 这行代码是智能筛选的核心。

它利用 @Conditional 系列注解作为"过滤器",只有满足特定条件的配置类才会被最终选中。这确保了自动配置的"按需生效"。

条件注解 作用 源码示例
@ConditionalOnClass 类路径下存在指定类时才生效 @ConditionalOnClass(DataSource.class)
@ConditionalOnMissingBean 容器中不存在指定 Bean 时才生效 @ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty 配置文件存在指定属性时才生效 @ConditionalOnProperty(name = "my.feature.enabled", ...)
@ConditionalOnWebApplication 当前是 Web 应用时才生效 @ConditionalOnWebApplication(type = ...)

WebMvcAutoConfiguration 为例,它的源码清晰地展示了多个条件注解的组合使用,确保只在 Web 环境下且相关类存在时才进行配置:

java 复制代码
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
public class WebMvcAutoConfiguration {
    // ... 自动配置 Web MVC 相关的 Bean
}

最终装配:Bean 的注册与创建

经过层层筛选后,最终胜出的自动配置类会被 Spring 当作普通的 @Configuration 类来处理。Spring 会解析这些类,并执行其中所有 @Bean 注解的方法,从而将框架所需的组件(如数据源、视图解析器等)注册到 IoC 容器中。

同时,这些配置类通常会配合 @ConfigurationProperties 注解,将 application.ymlapplication.properties 中的配置属性绑定到 Java 对象上,实现了配置的动态化。

总而言之,Spring Boot 的自动配置是一个高度自动化和智能化的过程,它通过 @EnableAutoConfiguration 触发,利用 AutoConfigurationImportSelector 加载候选配置,再通过 @Conditional 系列注解进行精确筛选,最终完成 Bean 的自动注册,完美诠释了"开箱即用"的开发体验。

自定义Starter

第一步:创建项目结构

Spring Boot 官方建议自定义 Starter 的命名格式为 xxx-spring-boot-starter。为了职责清晰,我们创建一个包含两个子模块的 Maven 项目:

  • hello-spring-boot-autoconfigure: 这是核心模块,包含所有的自动配置逻辑、业务代码和配置属性。
  • hello-spring-boot-starter : 这是一个"空壳"模块,其唯一作用是作为依赖入口,它只包含对 autoconfigure 模块的依赖。

最终的项目结构如下:

html 复制代码
hello-spring-boot-starter (父工程)
├── hello-spring-boot-autoconfigure
│   ├── src/main/java/com/example/hello/
│   │   ├── HelloService.java          (业务服务类)
│   │   ├── HelloAutoConfiguration.java (自动配置类)
│   │   └── HelloProperties.java       (配置属性类)
│   └── src/main/resources/META-INF/
│       └── spring.factories           (自动配置注册文件)
└── hello-spring-boot-starter
    └── pom.xml                        (依赖聚合)
第二步:实现 autoconfigure 模块
1. 编写业务服务类 (HelloService.java)

是你希望对外提供的核心功能,一个普通的 Java 类即可,无需任何 Spring 注解。

java 复制代码
package com.example.hello;

public class HelloService {
    private final String prefix;

    public HelloService(String prefix) {
        this.prefix = prefix;
    }

    public String sayHello(String name) {
        return prefix + ", " + name + "!";
    }
}
2. 编写配置属性类 (HelloProperties.java)

这个类用于将 application.ymlapplication.properties 中的配置绑定到 Java 对象中,让用户可以自定义行为。

java 复制代码
package com.example.hello;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "hello")
public class HelloProperties {
    // 默认前缀
    private String prefix = "Hello";

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }
}

用户可以在他们的配置文件中这样设置:hello.prefix=Hi

3. 编写自动配置类 (HelloAutoConfiguration.java)
java 复制代码
package com.example.hello;

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
// 当类路径下存在 HelloService 时才生效,这是一种安全检查
@ConditionalOnClass(HelloService.class)
// 启用配置属性,将 HelloProperties 注册为 Bean 并绑定配置
@EnableConfigurationProperties(HelloProperties.class)
public class HelloAutoConfiguration {

    // 当容器中没有 HelloService 这个 Bean 时,才创建并注册它
    // 这保证了用户可以自己定义 HelloService 来覆盖默认配置
    @Bean
    @ConditionalOnMissingBean
    public HelloService helloService(HelloProperties properties) {
        return new HelloService(properties.getPrefix());
    }
}
4. 注册自动配置类 (spring.factories)

这是让 Spring Boot 发现并加载你自定义配置类的关键。在 hello-spring-boot-autoconfigure 模块的 src/main/resources/META-INF/ 目录下,创建名为 spring.factories 的文件。

文件内容如下:

java 复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.hello.HelloAutoConfiguration

这行配置告诉 Spring Boot:"在启动时,请加载 com.example.hello.HelloAutoConfiguration 这个类"。

注意 :在 Spring Boot 2.7+ 版本中,推荐使用新的 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件来替代 spring.factories,内容只需写上自动配置类的全限定名即可。

第三步:实现 starter 模块

这个模块非常简单,它的 pom.xml 只需要声明对 autoconfigure 模块的依赖。

java 复制代码
<!-- hello-spring-boot-starter/pom.xml -->
<project>
    <!-- ... 其他项目信息 ... -->
    <artifactId>hello-spring-boot-starter</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>hello-spring-boot-autoconfigure</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</project>
第四步:打包并使用
  1. 打包 :在父工程 hello-spring-boot-starter 的根目录下,执行 mvn clean install 命令。这会将两个模块都安装到你本地的 Maven 仓库中。
  2. 使用 :现在,你可以在任何一个新的 Spring Boot 项目中引入你的 Starter。在 pom.xml 中添加依赖:
java 复制代码
<dependency>
    <groupId>com.example</groupId>
    <artifactId>hello-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

常用注解

启动与核心配置注解

注解 说明 典型应用场景
@SpringBootApplication 核心元注解。它是一个组合注解,包含了 @SpringBootConfiguration@EnableAutoConfiguration@ComponentScan 标注在主类上,作为 Spring Boot 应用的启动入口。
@EnableAutoConfiguration 告诉 Spring Boot 根据类路径下的依赖(jar包)自动配置 Bean。 通常包含在 @SpringBootApplication 中,极少单独使用。
@SpringBootConfiguration 标识当前类是一个配置类。它本质上是 @Configuration 的特化,用于标识 Spring Boot 的主配置类。 标注在主启动类上,表明该类也可以定义 Bean。
@AutoConfigurationPackage 将主类所在包(及子包)注册为自动配置包,用于 JPA 扫描实体或自定义 Starter 扫描。 包含在 @SpringBootApplication 中,决定了 @EntityScan 的默认范围。

自动配置与条件注解

注解 说明 典型应用场景
@ConditionalOnClass 当类路径下存在指定的类时,配置才生效。 检测是否引入了 DataSource.class,从而决定是否配置数据库连接池。
@ConditionalOnMissingBean 当 Spring 容器中不存在指定的 Bean 时,配置才生效。 提供默认实现(如默认的 DataSource),允许用户自定义 Bean 进行覆盖。
@ConditionalOnProperty 当配置文件(application.yml)中存在指定属性且值匹配时,配置才生效。 根据 my.feature.enabled=true 配置来决定是否开启某个功能模块。
@ConditionalOnWebApplication 当当前应用是 Web 应用时,配置才生效。 自动配置 DispatcherServlet 或 Web 相关的拦截器。
@ConditionalOnNotWebApplication 当当前应用不是 Web 应用时,配置才生效。 在非 Web 环境(如命令行应用)中配置特定的批处理逻辑。
@ConditionalOnResource 当类路径下存在指定资源文件时,配置才生效。 检测到 logback.xml 时才配置特定的日志工厂。
@AutoConfigureAfter / @AutoConfigureBefore 指定自动配置类的加载顺序,确保在某个自动配置类之后或之前加载。 自定义配置类需要在全局默认配置(如 DataSourceAutoConfiguration)之后生效时使用。

属性绑定与外部化配置

注解 说明 典型应用场景
@ConfigurationProperties 将配置文件(application.yml)中的属性值批量绑定到 Java Bean 中。支持松散绑定(如 my-prop 绑定到 myProp)。 定义一个 ServerProperties 类,自动读取 server.portserver.address 等配置。
@EnableConfigurationProperties 开启对 @ConfigurationProperties 的支持,并将指定的 Bean 注册到容器中。 在自定义 Starter 的配置类上使用,确保属性类能被 Spring 管理。

其他注解

注解 说明 典型应用场景
@ImportAutoConfiguration 导入指定的自动配置类,但不触发全量的 @EnableAutoConfiguration 在测试类或非主启动类中,手动引入某些自动配置功能(如 HttpAutoConfiguration)。
@TestConfiguration 用于定义测试专用的配置。它不会被主应用程序上下文扫描到,除非显式导入。 在测试代码中定义一些仅用于测试环境的 Bean 或 Mock 配置。
@SpringBootConfiguration 这是一个特殊的 @Configuration,专门用于标识 Spring Boot 应用的配置类。 通常作为 @SpringBootApplication 的一部分出现。
相关推荐
JuiceFS2 小时前
ARM 架构 JuiceFS 性能优化:基于 MLPerf 的实践与调优
后端·性能优化
为美好的生活献上中指2 小时前
*Java 沉淀重走长征路*之——《Linux 从入门到企业实战:一套六步法,带你打通运维与开发的任督二脉》
java·linux·运维·开发语言·阿里云·华为云·linux命令
Mr.wangh2 小时前
redis面试题总结
java·redis·面试
wuqingshun3141592 小时前
依赖注入的方式有几种,各是什么?
java·开发语言
颜酱2 小时前
回溯算法实战练习(2)
javascript·后端·算法
冬夜戏雪2 小时前
实习面经(十二)
java
lierenvip2 小时前
Spring Boot 整合 log4j2 日志配置教程
spring boot·单元测试·log4j
sxhcwgcy2 小时前
Spring Boot中集成MyBatis操作数据库详细教程
数据库·spring boot·mybatis
未秃头的程序猿2 小时前
Redis也能做消息队列!Spring Boot实战:从List到Stream的优雅实现
redis·后端