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 的一部分出现。
相关推荐
HoneyMoose3 分钟前
Jenkins Cloudflare 部署提示错误
java·servlet·jenkins
阿丰资源8 分钟前
基于SpringBoot的物流信息管理系统设计与实现(附资料)
java·spring boot·后端
Predestination王瀞潞11 分钟前
Java EE3-我独自整合(第四章:Spring bean标签的常见配置)
java·spring·java-ee
overmind12 分钟前
oeasy Python 121[专业选修]列表_多维列表运算_列表相加_列表相乘
java·windows·python
资深数据库专家13 分钟前
总账EBS 应用服务器1 的监控分析
java·网络·数据库
房开民15 分钟前
可变参数模板
java·开发语言·算法
t***54434 分钟前
如何在现代C++中更有效地应用这些模式
java·开发语言·c++
_深海凉_35 分钟前
LeetCode热题100-最小栈
java·数据结构·leetcode
不知名的忻39 分钟前
Morris遍历(力扣第99题)
java·算法·leetcode·morris遍历
daidaidaiyu1 小时前
一文学习入门 ThingsBoard 开源物联网平台
java·mqtt·spring