如何自定义 Spring Boot Starter?今天终于学会了~

举报
水滴技术 发表于 2023/06/15 17:13:16 2023/06/15
【摘要】 本篇主要讲述 Spring Boot Starter 的概念、命名规范,以及如何自定义一个 Starter,下面开始今天的内容。

本篇主要讲述 Spring Boot Starter 的概念、命名规范,以及如何自定义一个 Starter,下面开始今天的内容。

1 Starter 是什么

Spring Boot 的 Starter 是一组比较方便的依赖描述符,可以通过 Maven 将其打成jar包,并在你的项目中直接引用。

通过 Starter 你可以获取该功能的所有依赖,以及统一的配置,避免了复制、粘贴代码和依赖带来的麻烦。

Starter 主要使用了自动配置,所以它下面的所有组件会被 Spring Boot 通过META-INF/spring.factories文件注入IOC容器中。

2 命名规范

2.1 Starter 项目的命名规范

所有由Spring官方提供的Starter都会遵循spring-boot-starter-*的命名规范,其中*表示特定类型的应用程序。

而所有第三方的Starter,官方建议以项目名称开头,应遵循*-spring-boot-starter的命名规范,其中*表示第三方项目名称。

2.2 配置项的命名规范

如果自定义的 Starter 包含了配置项,请为它使用唯一的命名空间,不要与 Spring Boot 或其他组件产生冲突,例如:servermanagementspring

3 自定义一个 Starter

一个典型的 Starter 包含自动配置和自定义的核心代码。为了演示方便,本例中的核心代码就是一个“宠物”类,能够根据配置的“类型”来获取对应的“宠物”,下面看具体实现过程。

3.1 创建自定义的 Starter 工程

创建一个 Spring Boot 工程,将其命名为demo-spring-boot-starter。下图是工程完整目录结构,后面会逐一介绍它们。

3.2 POM中引入相关依赖

在POM中引入两个依赖:

  • spring-boot-starter:该依赖是 Starter 的核心,包括自动配置、日志和YAML的支持。我们所有自定义的 Starter 都应该直接或间接的引入该依赖。
  • spring-boot-configuration-processor:包含一个 Java 注解处理器,当使用@ConfigurationProperties注解配置自己的元数据时,需要引入此依赖。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

3.3 定义一个配置元数据类

自定义一个配置元数据类DemoProperties,用于映射YAML中的配置,使用@ConfigurationProperties注解需要指定配置项的前缀,此处的前缀为demo。当前配置项只有一个type字段,用于配置宠物的类型,那么该配置项的 Key 为:demo.type

@ConfigurationProperties(prefix = "demo")
public class DemoProperties {

    /**
     * 类型
     */
    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

3.4 定义一个配置类

先看自定义的宠物实体类Pet,很简单,只有一个name属性(此类纯属为了演示 Starter,无它)。

public class Pet {

    /**
     * 名称
     */
    private String name;

    public Pet(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

增一个配置类DemoAutoConfiguration,该类也非常简单:

  • 使用@Configuration注解声明该类为一个配置类;
  • 使用@EnableConfigurationProperties注解,引入自定义的配置元数据DemoProperties
  • 声明了一个Pet的 Bean,根据配置项中的type来返回不同的宠物。使用该 Bean 的目的,主要是用来演示 Starter 的自动配置。
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(DemoProperties.class)
public class DemoAutoConfiguration {

    private final DemoProperties demoProperties;

    public DemoAutoConfiguration(DemoProperties demoProperties) {
        this.demoProperties = demoProperties;
    }

    @Bean
    public Pet pet() {
        if (!StringUtils.hasText(demoProperties.getType())) {
            return new Pet("空的");
        }
        switch (demoProperties.getType()) {
            case "cat":
                return new Pet("小猫");
            case "dog":
                return new Pet("小狗");
            default:
                return new Pet("未知");
        }
    }
}

3.5 定义自动配置的候选

resources资源目录中增加文件META-INF/spring.factories,并将自定义的配置类DemoAutoConfiguration加入到自动配置类列表中,如下代码:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
io.github.gozhuyinglong.autoconfigure.DemoAutoConfiguration

这一步比较关键,需要重点说一下。

我们自定义Starter 的相关组件,肯定不在使用者自动扫描的目标中(目录结构不同),所以 Spring Boot 提供了这种机制,能够使第三方使用者发现这些组件。

Spring Boot 会检查所有发布的jar中是否包含META-INF/spring.factories文件,并将该文件中目标类注入IOC容器中,自动配置类就是使用这种方式加载的。

在上一篇《Spring Boot 自动配置的原理》中已经讲过自动配置的原理了,不了解的老铁建议先看下。

4 使用 Starter

我们再次创建一个工程,用于测试 Starter 是否生效。注意该工程的目录结构要与 Starter 的目录结构不同,这样才能测试出 Starter 中的组件是被 META-INF/spring.factories文件引入的,而非自动扫描。

4.1 创建一个客户端工程

创建一个 Spring Boot 工程,将其命名为 demo-client。下图是工程完整目录结构,后面会逐一介绍它们。

4.2 引入自定义 Starter 依赖

在POM文件中,引入刚者自定义的 Starter 依赖。为了便于测试,将spring-boot-starter-web也引入进来。

<dependency>
    <groupId>io.github.gozhuyinglong</groupId>
    <artifactId>demo-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

4.3 创建启动类

创建主启动类ClientApplication,注意该类的目录与 Starter 不同,也就是说当前工程不会通过@ComponentScan方式自动扫描 Starter 中的组件。

@SpringBootApplication
public class ClientApplication {

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

4.4 配置“宠物”的类型

自定义的 Starter 中可以配置宠物的类型,将其配置为dog

demo:
  type: dog

4.5 创建一个 Controller 类

创建一个ClientController类,用于测试 Starter 是否生效

@RestController
@RequestMapping("/client")
public class ClientController {

    @Autowired
    private Pet pet;

    @GetMapping("/test")
    public String test() {
        return pet.getName();
    }
}

4.6 测试 Starter

启动项目后,使用 Postman 或直接在浏览器中输入地址:http://127.0.0.1:8080/client/test,会发现输出了“小狗”,表示成功。

5 完整代码

完整代码请访问我的Github,若对你有帮助,欢迎给个⭐,感谢~~🌹🌹🌹

https://github.com/gozhuyinglong/blog-demos/tree/main/springboot-family

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。