说到Spring Boot自定义starter,首先我们要先了解Spring Boot官方定义starter的原因,从中明白自定义starter的意义,学习定义starter的标准,然后自定义的starter
Spring Boot很容易整合其他组件,比如对于SpringMVC而言,我们只需要导入Spring-boot-starter-web就可以直接编写Controller,这个依赖不仅仅是导入了一个jar包,还把集成SpringMVC所需要的所有jar包都引入了
对于不同组件的集成都有对应的starter,如:整合Redis组件,我们导入spring-boot-starter-redis就可以把Redis所需的jar包导入,在starter中不仅包含了集成某个组件所需的所有jar包,还包括集成该组件的配置类。总结如下:
- 简化依赖管理 - starter是预配置的依赖项集合,包含了构建应用所需的必要组件和配置,可以避免开发者手动添加和管理大量的依赖
- 自动配置 - starter不仅提供了必要的依赖,还提供了自动配置功能,这意味着当开发者引入某个starter依赖时,Spring Boot会自动配置与该starter相关的功能和组件,无需开发者手动编写配置代码
- 快速集成 - 通过引入starter依赖可以快速集成各种功能
- 统一标准,易于扩展和定制 - 官方starter遵循了统一的项目结构和设计规范,有助于统一团队成员的开发规范,因此开发者可以根据该标准自定义starter
所以当我们开发一个通用组件,它会被多个项目依赖时,那就可以自定义一个自动装配的starter
那我们现在就可以仿照Spring Boot官方的starter自定义一个自动装配Redis的starter,当某个项目引入该starter之后就可以根据默认配置自动连接Redis,实现步骤如下:
- 创建一个Maven工程,导入操作Redis所需的jar包
- 定义一个Properties类,用来加载yml配置中的Redis配置类
- 新建自动装配类,使用@Configuration和@Bean来进行自动装配
- 在资源文件夹resources\META-INF下创建spring.factories文件,把自动配置类配置进去,让Spring Boot可以自动去加载
- 创建一个Maven工程,pom文件中引入SpringBoot基础依赖以及jedis的基础依赖(用于测试)
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starters</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencies>
<!-- SpringBoot自动配置基础依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- SpringBoot核心基础依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<!-- 使用jedis操作Redis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.6</version>
</dependency>
</dependencies>
- 定义Properties配置类,用于读取yml中的配置
//@ConfigurationProperties: 把 "spring.redis" 前缀下的配置同名绑定到该对象的字段上
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
//redis主机
private String host = "127.0.0.1";
//redis密码
private String password = "123456";
//redis端口
private int port = 6379;
//超时时间,1秒超时
private int timeout = 1000;
//最大空闲
private int maxIdle = 8;
//最大链接
private int maxTotal = 8;
//最大等待超时
private long maxWaitMillis = -1;
//开启测试
private boolean testOnBorrow = false;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
public int getMaxTotal() {
return maxTotal;
}
public void setMaxTotal(int maxTotal) {
this.maxTotal = maxTotal;
}
public long getMaxWaitMillis() {
return maxWaitMillis;
}
public void setMaxWaitMillis(long maxWaitMillis) {
this.maxWaitMillis = maxWaitMillis;
}
public boolean isTestOnBorrow() {
return testOnBorrow;
}
public void setTestOnBorrow(boolean testOnBorrow) {
this.testOnBorrow = testOnBorrow;
}
}
- 创建自动配置类、注册对象
@Configuration
//如果有Jedis.class这个类就创建Bean
@ConditionalOnClass({Jedis.class,JedisPoolConfig.class})
//如果还没有创建Jedis,就创建
@ConditionalOnMissingBean(Jedis.class)
//@EnableConfigurationProperties : 启用RedisProperties
@EnableConfigurationProperties(RedisProperties.class)
public class RedisAutoConfiguration {
@Bean
public JedisPool jedisPool(RedisProperties redisProperties){
JedisPoolConfig config = new JedisPoolConfig();
//最大空闲连接数
config.setMaxIdle(redisProperties.getMaxIdle());
//最大链接对象数
config.setMaxTotal(redisProperties.getMaxTotal());
//链接超时时间
config.setMaxWaitMillis(redisProperties.getMaxWaitMillis());
//获取连接是测试连接是否畅通
config.setTestOnBorrow(redisProperties.isTestOnBorrow());
//参数:配置对象,redis主机地址 ,超时时间,密码
return new JedisPool(config,redisProperties.getHost(),redisProperties.getPort(),redisProperties.getTimeout(),redisProperties.getPassword());
}
@Bean
public RedisTemplate redisTemplate(JedisPool jedisPool){
return new RedisTemplate(jedisPool);
}
}
- 创建Template,用于操作Redis的工具类
public class RedisTemplate {
//连接池
private JedisPool jedisPool;
public RedisTemplate(JedisPool jedisPool){
this.jedisPool = jedisPool;
}
public RedisTemplate(){}
public Jedis getJedis(){
return jedisPool.getResource();
}
//保存字符串
public String set(String key ,String value){
Jedis jedis = getJedis();
String result = jedis.set(key , value);
jedis.close();
return result;
}
//获取字符串
public String get(String key){
Jedis jedis = getJedis();
String result = jedis.get(key);
jedis.close();
return result;
}
}
- 在资源文件夹resources\META-INF下创建spring.factories文件,将配置类的全限定类名放入
org.springframework.boot.autoconfigure.EnableAutoConfiguration=配置类的全限定类名
- 项目结构如下
- 在terminal命令窗口执行:mvn install,把工程打包到本地仓库
接下来就是在项目中引入该starter依赖,当项目启动,Spring Boot就会加载到我们自定义Maven工程下resources\META-INF\spring.factories文件中的配置类,其中的JedsPool和RedisTemplate都会被注册到Spring容器中,后续注入RedisTemplate使用即可
- 项目的pom文件中引入自定义starter依赖
<dependency>
<groupId>项目的组Id</groupId>
<artifactId>自定义starter Maven工程名</artifactId>
<version>版本号</version>
</dependency>
- 项目的yml中配置相关数据
spring:
redis:
password: 123456
host: 127.0.0.1
port: 6379
- 编写Controller,注入RedisTemplate使用
到这里我们通过对Spring Boot官方starter的了解,仿照它自定义了一个starter并使用,我相信大家对Spring Boot自动装配的原理也清晰了许多,如果还要深入了解其原理,那我们就需要去跟踪Spring Boot自动装配原理的源码了,希望这篇文章能对大家有所帮助!