前言
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 的作用