写点什么

Spring Boot「12」自定义 starter

作者:Samson
  • 2022-10-23
    上海
  • 本文字数:2486 字

    阅读完需:约 8 分钟

Spring Boot「12」自定义 starter

基于 Spring Boot 的应用开发之所以如此便捷,一个非常重要的原因就是拥有丰富的 starter。基于 starter,开发者可以避免冗长的配置,而直接上手编写业务代码。除了那些常用的 starter 外,Spring Boot 支持自定义 starter。今天,我们一块来学习下如何实现一个自定义的 starter。


实现一个自定 starter 需要实现两个部分内容:


  1. 实现一个自动配置类,根据条件来自动化的构造 Bean,另外需要一个外部配置属性对应的 POJO 类,用来保存配置信息;

  2. 构造一个 pom.xml 文件,引入必要的依赖


接下来,我们逐步实现一个可以 say hello 的 starter。

01-实现自动配置类

首先,我们创建一个 say-hello 的工程(这里我们同样复用之前的 payroll 工程,在其下增加一个 say-hello 的模块)。在这个模块里,需要增加三个类:


  • SayHello.class,是一个工具类:


public class SayHello {    private String name;    private String message;
public SayHello(String name, String message) { this.name = name; this.message = message; }
public void greeting() { System.out.println("Hi~, " + name + ", " + message); }}
复制代码


SayHello 只有 2 个属性和一个方法 greeting,会向控制台打印欢迎消息。


  • SayHelloAutoConfiguration.class,自动配置类,标注了条件化注解:


@Configuration@EnableConfigurationProperties(SayHelloProperties.class)@ConditionalOnClass(SayHello.class)public class SayHelloAutoConfiguration {
private SayHelloProperties sayHelloProperties;
@Autowired public SayHelloAutoConfiguration(SayHelloProperties sayHelloProperties) { this.sayHelloProperties = sayHelloProperties; }
@Bean @ConditionalOnMissingBean public SayHello sayHello() { return new SayHello(sayHelloProperties.getUserName(), sayHelloProperties.getMessage()); }}
复制代码


@Configuration表示这是一个配置类,用来自动化配置 SayHello 工具类。@EnableConfigurationProperties(SayHelloProperties.class)会自动创建一个 SayHelloProperties 对象,并将外部属性值绑定到该对象上。@ConditionalOnClass(SayHello.class)表示该配置类中定义的 Bean 只有在项目的 classpath 中存在 SayHello.class 时才有效@ConditionalOnMissingBean表示只有在当前容器中并不包含 SayHello.class 类型的实例时,该 Bean 方法才生效,创建一个 Bean 对象。


为了是自动配置生效,还需要在 META-INF/spring.factories 中增加如下内容:


org.springframework.boot.autoconfigure.EnableAutoConfiguration=\  self.samson.example.SayHelloAutoConfiguration
复制代码


  • SayHelloProperties.class,标注了@ConfigurationProperties,表示外部化配置信息的 POJO:


@ConfigurationProperties(prefix = "example.say.hello")public class SayHelloProperties {    private String userName;    private String message;    // getters & setters and constructors}
复制代码


注:上面的写法可能并不是一个标准的 starter,标准的 starter 项目中应该不包含任何代码,仅包含 pom.xml 上述 SayHello.class 应该是在某个应用包中;ConfigurationProperties.class 和 SayHelloAutoConfiguration.class 应该在某个 auto-configure 包中。

02-定义 pom.xml

因为我们的项目比较简单,所以 pom.xml 中并不需要配置什么。在实际的 starter 项目中,例如 spring-boot-starter-validation 中,jar 包中基本是不包含任何内容的。starter 最重要的是它的 pom.xml 文件,它描述了所有的依赖项。我们仍然以 spring-boot-starter-validation 为例,它的 pom.xml 中的主要内容包括:


<dependencies>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter</artifactId>        <version>2.7.4</version>        <scope>compile</scope>    </dependency>    <dependency>        <groupId>org.apache.tomcat.embed</groupId>        <artifactId>tomcat-embed-el</artifactId>        <version>9.0.65</version>        <scope>compile</scope>    </dependency>    <dependency>        <groupId>org.hibernate.validator</groupId>        <artifactId>hibernate-validator</artifactId>        <version>6.2.5.Final</version>        <scope>compile</scope>    </dependency></dependencies>
复制代码


它定义了 spring-validator 所有的依赖项,所有希望使用 spring-validator 的项目只需要引入 starter,而不需要手动的引入每一个依赖。简化依赖配置也是 starter 设计的初衷之一。

03-使用 starter

使用自定义的 starter 与使用其他 starter 的步骤没有其他区别,只需要在 pom.xml 中增加依赖即可。


接下来演示如何使用 say-hello 中的 SayHello。


我们在 classpath:/properties/say-hello.properties 中增加如下配置,以便使 SayHelloProperties 中的属性能够有值绑定。


example.say.hello.user-name=Samsonexample.say.hello.message=Nice to meet you!
复制代码


然后,在 Application 类上通过@PropertyResource中引入外部配置文件。


@PropertySource("classpath:/properties/say-hello.properties")public class ListAllManagedBeanApplication {    public static void main(String[] args) {        final ConfigurableApplicationContext ctx = SpringApplication.run(ListAllManagedBeanApplication.class, args);
final SayHello greeter = ctx.getBean(SayHello.class);
greeter.greeting(); }}
复制代码


运行程序,即可在控制台得到如下输出:


Hi~, Samson, Nice to meet you!
复制代码

03-总结

今天我们一块学习了如何实现一个 starter,使用 starter 是一种良好地编程或者项目管理风格。通过 starter,依赖管理和升级都比较方便,只需要升级 starter 的版本即可。不过,starter 也不是完全没有缺点,过度依赖 starter 可能会使得依赖关系更难理解。

发布于: 刚刚阅读数: 4
用户头像

Samson

关注

还未添加个人签名 2019-07-22 加入

InfoQ签约作者 | 阿里云社区签约作者

评论

发布
暂无评论
Spring Boot「12」自定义 starter_Java_Samson_InfoQ写作社区