一、介绍与定义
本章用于记录自定义Springboot-starter
的学习过程。
在我们自定义starter
之前,我们首先观察一下SpringBoot
自身的starter
的形式都是什么样的。我们以spring-boot-starter-web
为例。
通过spring-boot-starter-web
,可以看出当前引入的依赖是空的JAR
文件。它的作用是仅提供辅助依赖管理,这些依赖可用于自动装配或者其他类库。继续点入,可以看见其引入了spring-boot-starter
,再进一步点入,又能看见其引入了spring-boot-autoconfigure
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.4.0</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>2.4.0</version> <scope>compile</scope> </dependency>
|
从以上总结出,starter
的场景需要以下两个模块:
- 启动器模块 –
xx-starter
- 自动配置模块
自定义starters
,即对自动装配的组件交给SpringBoot
管理,继而供我们使用,需满足以下条件:
同样,以WebMvcAutoConfiguration
为例的自动配置编写:
1 2 3 4 5 6 7
| @Configuration @ConditionalOnXXX @AutoConfigureAfter @Bean
@ConfigurationPropertie @EnableConfigurationProperties
|
自动配置类要是能够加载,那么就需要将启动加载的自动配置类,配置在META-INF/spring.factories
1 2 3
| org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
|
所有自动配置:首先它是一个自动配置类;设定起作用的条件,再将相关配置加入到容器中。
启动器:启动器模块是一个空的JAR
文件,仅提供辅助性依赖管理,这些依赖用于自动装配或者其他类库。
总结starter
的使用模式:
首先编写xxx-starter
启动器,继续编写一个xxx-starter-autoconfigurer
自动配置类,我的启动器则依赖此自动配置类。当需要使用我们的starter
时,则只需要直接依赖我们的xxx-starter
启动器即可。
命名规范:
- 官方命名空间
- 前缀:
spring-boot-starter-
- 模式:
spring-boot-starter-模块名
- 例子:
spring-boot-starter-web
、spring-boot-starter-actuator
、spring-boot-starter-jdbc
- 自定义命名空间
- 后缀:
-spring-boot-starter
- 模式:
模块-spring-boot-starter
- 举例:
mybatis-spring-boot-starter
自定义starter
步骤:创建两个模块。一个作为启动器,一个作为自动配置模块。最终的目的,启动器中包含着自动配置模块,导入依赖时是导入启动器。
二、自定义Starter的编写
新建工程,创建两个模块。分别作为启动器模块和自动配置模块。自定义hello
的starter
。
启动器模块命名:selfdef-spring-boot-starter
。
自动配置模块:selfdef-spring-boot-starter-autoconfigurer
启动器模块:
按照之前的描述,启动器模块不写入任何内容,只在pom.xml
中引入自动配置模块的依赖。即:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?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>cn.chemlez</groupId> <artifactId>selfdef-springboot-starter</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>cn.chemlez.starter</groupId> <artifactId>selfdef-spring-boot-starter-autoconfigurer</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>
|
自动配置模块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.0</version> <relativePath/> </parent> <groupId>cn.chemlez.starter</groupId> <artifactId>selfdef-spring-boot-starter-autoconfigurer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sefldef-spring-boot-starter-autoconfigurer</name> <description>Demo project for Spring Boot</description>
<properties> <java.version>1.8</java.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> </dependencies> </project>
|
编写配置类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @ConfigurationProperties(prefix = "chemlez.hello") public class HelloProperties {
private String prefix; private String suffix;
public String getPrefix() { return prefix; }
public void setPrefix(String prefix) { this.prefix = prefix; }
public String getSuffix() { return suffix; }
public void setSuffix(String suffix) { this.suffix = suffix; } }
|
编写HelloService
类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class HelloService {
HelloProperties helloProperties;
public String sayHello(String name) {
return helloProperties.getPrefix() + "-" + name + helloProperties.getSuffix(); }
public HelloProperties getHelloProperties() { return helloProperties; }
public void setHelloProperties(HelloProperties helloProperties) { this.helloProperties = helloProperties; }
}
|
供调用starter
的使用者使用的类。最终这个类通过自动配置类,将其添加进容器中,供使用者使用。
编写自动配置类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Configuration @ConditionalOnWebApplication @EnableConfigurationProperties(HelloProperties.class) // 使属性文件生效 public class HelloServiceAutoConfiguration {
@Autowired HelloProperties helloProperties;
@Bean public HelloService helloService() { HelloService service = new HelloService(); service.setHelloProperties(helloProperties); return service; } }
|
至此,我们编写了一个简单的starter
。其作用,就是在页面中返回HelloService
中的以下这个函数的返回值:
1 2 3
| public String sayHello(String name) { return helloProperties.getPrefix() + "-" + name + helloProperties.getSuffix(); }
|
最后,分别将selfdef-spring-boot-starter
、selfdef-spring-boot-starter-autoconfigurer
通过Maven
中的install
,将其打包进Maven
仓库供我们使用依赖。
注意:因为,selfdef-spring-boot-starter
中引入了selfdef-spring-boot-starter-autoconfigurer
,供在打包时,先打包后者,再打包前者。
三、测试
创建一个新的web
工程的Springboot
项目,在其pom.xml
文件中,引入上面我们自定义的selfdef-spring-boot-starter
依赖,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.0</version> <relativePath/> </parent> <groupId>cn.chemlez</groupId> <artifactId>spring-boot-starter-09</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-boot-starter-09</name> <description>Demo project for Spring Boot</description>
<properties> <java.version>1.8</java.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>cn.chemlez</groupId> <artifactId>seldef-springboot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
|
编写控制器类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Controller public class HelloController {
@Autowired private HelloService helloService;
@RequestMapping("/hello") @ResponseBody public String hello() {
String hello = helloService.sayHello("Tom"); return hello; } }
|
配置文件的编写。因为我们在第二节中的配置类中,设定了前缀(prefix
)和后缀(suffix
)。因此,要在配置文件中,将其配置出。
1 2 3
| chemlez.hello: prefix: 张三 suffix: 李四
|
启动Springboot
项目,访问8080
端口下的hello
。结果: