SpringBoot自定义starter入门

前言

SpringBoot中的starter是一种重要的机制,遵循"约定优于配置"的理念,应用者只需要添加starter的maven依赖,
SpringBoot就会自动扫描并加载相应的配置。为了更好的理解SpringBoot的原理,我们定义一个自己的starter。

自定义starter

命名规范

官方的starter的命名格式为 spring-boot-starter-{name} ,例如 spring-boot-starter-web,spring-boot-starter-security。
非官方的starter的命名格式为 {name}-spring-boot-starter,例如 mybatis-spring-boot-starter,jasypt-spring-boot-starter,
我们定义的名称为 mystarter-spring-boot-starter。

创建maven项目并添加依赖

pom文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.imooc</groupId>
  <artifactId>mystarter-spring-boot-starter</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure</artifactId>
      <version>2.1.0.RELEASE</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>11</source>
          <target>11</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

定义属性配置类

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

@ConfigurationProperties(prefix = "mystarter")
public class MyStarterServiceProperties {

  private String username;
  private String password;

  public void setUsername(String username) {
    this.username = username;
  }

  public String getUsername() {
    return username;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  public String getPassword() {
    return password;
  }

  @Override
  public String toString() {
    return username + "," + password;
  }
}

一个普通的java类,@ConfigurationProperties注解可以将相同前缀的配置信息映射成实体类。类似于mybatis中的MybatisProperties。

定义一个Service

public class MyStarterService {

  private String username;
  private String password;

  public MyStarterService(String username, String password) {
    this.username = username;
    this.password = password;
  }

  public void operator() {
    System.out.println(username + "," + password);
  }
}

一个普通的业务功能类,严格来说,此类应该放在单独的项目中,和这个starter项目分开。

定义自动配置类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnClass(MyStarterService.class)
@EnableConfigurationProperties(MyStarterServiceProperties.class)
public class MyStarterAutoConfigure {

  @Autowired
  private MyStarterServiceProperties properties;

  @Bean
  public MyStarterService myStarterService() {
    System.out.println("mystarter-spring-boot-starter run success:" + properties);
    return new MyStarterService(properties.getUsername(), properties.getPassword());
  }
}

实现starter的核心类,用来初始化starter中的相关bean,类似mybatis中的MybatisAutoConfiguration。

  • @Configuration,表示当前类是一个配置类,会解析包含@Bean注解的方法。
  • @ConditionalOnClass,只有在classpath中找到MyStarterService类的情况下,当前配置类才会生效。
  • @EnableConfigurationProperties,用来开启对@ConfigurationProperties注解的支持。

创建spring.factories文件

创建META-INF文件夹,并在文件夹下创建spring.factories文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.imooc.mystarterspringboot.MyStarterAutoConfigure

SpringBoot会在启动时查询所有的spring.factories文件,找到key为EnableAutoConfiguration类全路径的value列表并自动装配到IOC容器,类似于java中的SPI机制。

核心解析类为SpringFactoriesLoader。

使用starter

将starter项目install到本地仓库,在另一个项目中使用

引入依赖

<dependency>
   <groupId>com.imooc</groupId>
   <artifactId>mystarter-spring-boot-starter</artifactId>
   <version>1.0-SNAPSHOT</version>
</dependency>

添加yaml配置

mystarter:
  username: lisi
  password: 123

创建测试类

@RestController
@RequestMapping("/test")
public class TestController {

  @Autowired
  private MyStarterService myStarterService;

  @GetMapping("/testMyStarter")
  public String testMyStarter() {
    myStarterService.operator();
    return "success";
  }
}

访问这个url,会在控制台打印lisi,123,符合预期。

关于spring-boot-configuration-processor

我们在配置文件中输入官方配置时,IDEA会自动提示

但我们自己定义的starter却没有提示

这就是spring-boot-configuration-processor起的作用,它是一个注解处理器,会在编译时根据@ConfigurationProperties注解定义的类
在META-INF文件夹下创建spring-configuration-metadata.json文件,这是一种元数据文件,IDEA会处理此文件来给出提示信息。

starter项目添加依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-configuration-processor</artifactId>
  <version>2.1.0.RELEASE</version>
</dependency>

重新install到本地仓库

生成的spring-configuration-metadata.json文件

提示效果

参考

你一直用的 Spring Boot Starter 是怎么回事
SpringBoot应用篇(一):自定义starter
spring-boot-configuration-processor 的作用

posted @ 2021-08-28 18:39  strongmore  阅读(407)  评论(0编辑  收藏  举报