前言
starter会把所有用到的依赖包都包含进来,避免开发者自己去引入依赖所带来的麻烦。
虽然不同的starter实现起来各有差异,但是他们基本上都会使用到两个相同的内容:ConfigurationProperties
和AutoConfiguration
。
Starter是一组可以让你很方便的在应用增加的依赖关系描述符的集合。或者可以这样理解,平时我们开发的时候很多情况下都会有一个模块依赖另一个模块,这个时候我们一般都是采用maven的模块依赖,进行模块的依赖,但是这种情况下我们完全可以采用Starter的方式,将需要被依赖的模块用Starter的方式去开发,最后直接引入一个Starter也可以达到这样的效果。
命名规则
由于SpringBoot官方本身就提供了很多Starter,为了区别那些是官方的,哪些是第三方的,所以SpringBoot官方提出:
第三方提供的Starter统一用xxx-spring-boot-starter
而官方提供的Starter统一用spring-boot-starter-xxx。
需求
下边我们将实现一个简易版的starter组件
项目结构
创建Starter
首先我们创建一个
spring-boot-starter-demo的项目,并添加依赖,如下
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.jack.cen.starters</groupId>
<artifactId>spring-boot-starter-demo</artifactId>
<version>1.0</version>
<name>spring-boot-starter-demo</name>
<description>spring-boot-starter-demo</description>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
</plugins>
</build>
</project>
编写配置类
创建一个SpringBootStarterDemoProperties用于保存配置信息
package com.jack.cen.starters.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 配置
*
* @author cenjianhua
* @date 2021/11/04
*/
@Data
@ConfigurationProperties(prefix = "springboot.starter.demo")
public class SpringBootStarterDemoProperties {
/**
* 测试属性
*/
private String testProperties;
}
创建自动化配置类
- 创建一个
AutoConfiguration
,引用定义好的配置信息 - 在
AutoConfiguration
中实现bean的注入以及配置信息的读取 - 把这个类加入spring.factories配置文件中进行声明
package com.jack.cen.starters.config; import com.jack.cen.starters.annotation.EnableSpringBootStarterDemoConfiguration; import com.jack.cen.starters.service.SpringBootStarterDemoService; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * SpringBootStarterDemo自动注入配置 * * @author cenjianhua * @date 2022/02/24 */ @Configuration @ConditionalOnBean(annotation = EnableSpringBootStarterDemoConfiguration.class) @EnableConfigurationProperties(SpringBootStarterDemoProperties.class) public class SpringBootStarterDemoAutoConfiguration { @Bean @ConditionalOnMissingBean SpringBootStarterDemoService learningCenterReqService() { return new SpringBootStarterDemoService(); } }
创建spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.jack.cen.starters.config.SpringBootStarterDemoAutoConfiguration
创建EnableSpringBootStarterDemoConfiguration
用于是否启用配置的注解
package com.jack.cen.starters.annotation;
import java.lang.annotation.*;
/**
* 注解配置
*
* @author cenjianhua
* @date 2021/11/04
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface EnableSpringBootStarterDemoConfiguration {
}
创建SpringBootStarterDemoService,具体的业务类 实现自己的业务逻辑,这里只做简单的示例,获取配置文件的值。在引用类里使用@Resource/@Autowired加载使用。
package com.jack.cen.starters.service;
import com.jack.cen.starters.config.SpringBootStarterDemoProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Resource;
/**
* 业务逻辑
*
* @author cenjianhua
* @date 2021/11/04
*/
public class SpringBootStarterDemoService {
private static final Logger LOGGER = LoggerFactory.getLogger(SpringBootStarterDemoService.class);
@Resource
private SpringBootStarterDemoProperties springBootStarterDemoProperties;
/**
* 获取测试属性
*
* @return {@link String}
*/
private String getTestProperties() {
String testProperties = springBootStarterDemoProperties.getTestProperties();
LOGGER.info("testProperties:" + testProperties);
return testProperties;
}
}
接下来,我们通过运行mvn install
命令,将这个项目打成jar包部署到本地仓库,提供给另一个服务调用。
测试
创建一个测试项目,依赖spring-boot-starter-demo
<dependency> <groupId>com.jack.cen.starters</groupId> <artifactId>spring-boot-starter-demo</artifactId> <version>1.0</version> </dependency>
application.properties
配置文件
springboot.starter.demo.test-properties=123
启动类:
@SpringBootApplication @EnableSpringBootStarterDemoConfiguration public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
测试类
@SpringBootTest class DemoApplicationTests { @Resource private SpringBootStarterDemoService service; @Test void contextLoads() { String testProperties = service.getTestProperties(); System.out.println(testProperties); } }
测试结果
从结果中,我们看到starter中定义的SpringBootStarterDemoService
已成功注入到测试项目中。