创建自定义 Spring Boot Starter

更新于 2025-12-30

baeldung 2017-04-19

1. 概述

Spring Boot 核心开发团队为大多数流行的开源项目提供了 starter(启动器),但我们并不局限于这些官方 starter。

我们也可以编写自己的自定义 starter。如果我们在组织内部有一个通用库,并且计划在 Spring Boot 项目中使用它,那么为其编写一个 starter 将是一个很好的实践。

这些 starter 能让开发者避免冗长的配置,快速启动开发工作。然而,由于很多操作都在后台自动完成,有时很难理解:为什么仅仅添加一个注解或在 pom.xml 中引入一个依赖,就能启用如此多的功能。

在本文中,我们将揭开 Spring Boot 的“魔法”面纱,深入理解其背后的工作原理。然后,我们将利用这些概念,为自己的自定义库创建一个 starter。

2. 揭秘 Spring Boot 的自动配置机制

2.1 自动配置类

从 Spring Boot 2.7 版本开始,应用启动时会从文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中读取自动配置类的导入列表。我们可以查看 spring-boot-autoconfigure 项目中的该文件内容作为示例:

...
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
...

如上所示,文件中的每一行都包含一个 Spring Boot 尝试执行的自动配置类的全限定名。因此,根据这段代码片段,Spring Boot 将尝试运行 RabbitMQ、Cassandra、MongoDB 和 Hibernate 的相关配置类。

这些配置类是否真正执行,取决于 classpath 上是否存在相关的依赖类。例如,如果 classpath 中存在 MongoDB 相关的类,MongoAutoConfiguration 就会被执行,并初始化所有与 MongoDB 相关的 Bean。

这种条件化初始化是通过 @ConditionalOnClass 注解实现的。让我们看一下 MongoAutoConfiguration 类中的代码片段,以了解其用法:

@Configuration
@ConditionalOnClass(MongoClient.class)
@EnableConfigurationProperties(MongoProperties.class)
@ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")
public class MongoAutoConfiguration {
    // 配置代码
}

如上所示,只要 classpath 中存在 MongoClient 类,该配置类就会被加载,并使用默认配置初始化一个 MongoClient Bean 并注册到 Spring 容器中。

注意:如果使用的 Spring Boot 版本低于 2.7,则自动配置类是从 META-INF/spring.factories 文件中读取的。例如,在 spring-boot-autoconfigure 项目中可以找到类似内容:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration

可以看到,该文件采用逗号分隔的单行列表格式来指定自动配置类。如上例所示,可以使用反斜杠 \ 进行换行,使内容更易读。

2.2 从 application.properties 文件中读取自定义属性

Spring Boot 在初始化 Bean 时会使用一些预设的默认值。为了覆盖这些默认值,我们通常在 application.properties 文件中使用特定名称声明属性。Spring Boot 容器会自动读取这些属性。

下面我们看看它是如何工作的。

MongoAutoConfiguration 的代码片段中,@EnableConfigurationProperties 注解指定了 MongoProperties 类,该类用于封装自定义属性:

@ConfigurationProperties(prefix = "spring.data.mongodb")
public class MongoProperties {

    private String host;

    // 其他字段及其标准 getter 和 setter 方法
}

属性名由前缀(prefix)加上字段名构成。因此,要设置 MongoDB 的主机地址,只需在属性文件中写入:

spring.data.mongodb.host = localhost

同样,该类中其他字段的值也可以通过属性文件进行设置。

3. 创建自定义 Starter

基于第 2 节介绍的概念,要创建一个自定义 starter,我们需要编写以下组件:

  • 一个用于我们库的自动配置类,以及一个用于自定义配置的属性类。
  • 一个 starter 的 pom.xml 文件,用于引入库本身和自动配置模块的依赖。

为了演示,我们创建了一个简单的问候语库(greeter library),它可以根据一天中不同时段的配置参数输出相应的问候消息。我们还将创建一个示例 Spring Boot 应用程序,以展示自动配置模块和 starter 的使用方式。

3.1 自动配置模块

我们将自动配置模块命名为 greeter-spring-boot-autoconfigure。该模块包含两个主要类:

  • GreeterProperties:用于通过 application.properties 文件设置自定义属性。
  • GreeterAutoConfiguration:用于为 greeter 库创建 Bean。

以下是这两个类的代码:

@ConfigurationProperties(prefix = "baeldung.greeter")
public class GreeterProperties {

    private String userName;
    private String morningMessage;
    private String afternoonMessage;
    private String eveningMessage;
    private String nightMessage;

    // 标准的 getter 和 setter 方法
}
@Configuration
@ConditionalOnClass(Greeter.class)
@EnableConfigurationProperties(GreeterProperties.class)
public class GreeterAutoConfiguration {

    @Autowired
    private GreeterProperties greeterProperties;

    @Bean
    @ConditionalOnMissingBean
    public GreetingConfig greeterConfig() {

        String userName = greeterProperties.getUserName() == null
          ? System.getProperty("user.name") 
          : greeterProperties.getUserName();
        
        // ...

        GreetingConfig greetingConfig = new GreetingConfig();
        greetingConfig.put(USER_NAME, userName);
        // ...
        return greetingConfig;
    }

    @Bean
    @ConditionalOnMissingBean
    public Greeter greeter(GreetingConfig greetingConfig) {
        return new Greeter(greetingConfig);
    }
}

我们还需要将 GreeterAutoConfiguration 的全限定类名添加到文件
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中:

com.baeldung.greeter.autoconfigure.GreeterAutoConfiguration

注意:如果你使用的是 Spring Boot 2.7 之前的版本,则需要在
src/main/resources/META-INF/spring.factories 文件中添加如下内容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.baeldung.greeter.autoconfigure.GreeterAutoConfiguration

在应用启动时,如果 classpath 中存在 Greeter 类,GreeterAutoConfiguration 就会被执行。成功执行后,它会通过 GreeterProperties 读取配置,并向 Spring 应用上下文中注册 GreetingConfigGreeter Bean。

@ConditionalOnMissingBean 注解确保只有在容器中尚未存在这些 Bean 时才会创建它们。这使得开发者可以通过在自己的 @Configuration 类中定义同名 Bean 来完全覆盖自动配置的行为。

3.2 创建 pom.xml

接下来我们创建 starter 的 pom.xml 文件,用于引入自动配置模块和 greeter 库的依赖。

按照命名规范,所有非 Spring Boot 官方维护的 starter 都应以库名开头,并以 -spring-boot-starter 作为后缀。因此,我们将 starter 命名为 greeter-spring-boot-starter

<project ...>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.baeldung</groupId>
    <artifactId>greeter-spring-boot-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>

        <dependency>
            <groupId>com.baeldung</groupId>
            <artifactId>greeter-spring-boot-autoconfigure</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>com.baeldung</groupId>
            <artifactId>greeter</artifactId>
            <version>${greeter.version}</version>
        </dependency>

    </dependencies>

    <properties>
        <greeter.version>0.0.1-SNAPSHOT</greeter.version>
    </properties>
</project>

3.3 使用 Starter

现在我们创建一个名为 greeter-spring-boot-sample-app 的示例 Spring Boot 应用,来使用这个 starter。只需在 pom.xml 中添加如下依赖:

<dependency>
    <groupId>com.baeldung</groupId>
    <artifactId>greeter-spring-boot-starter</artifactId>
    <version>${greeter-starter.version}</version>
</dependency>

Spring Boot 会自动完成所有配置,Greeter Bean 将可以直接注入并使用。

我们还可以通过在 application.properties 文件中使用 baeldung.greeter 前缀来自定义 GreeterProperties 的默认值:

baeldung.greeter.userName=Baeldung
baeldung.greeter.afternoonMessage=Woha\ Afternoon

最后,在应用程序中使用 Greeter Bean:

@SpringBootApplication
public class GreeterSampleApplication implements CommandLineRunner {

    @Autowired
    private Greeter greeter;

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

    @Override
    public void run(String... args) throws Exception {
        String message = greeter.greet();
        System.out.println(message);
    }
}

4. 结论

在本教程中,我们重点介绍了如何创建一个自定义的 Spring Boot starter,并深入探讨了 starter 与自动配置机制如何协同工作,从而大幅减少手动配置的工作量。