之所以想要学习这个starter并不是对技术的热爱,而是来自一次领导的鞭策,不过通过这次的学习倒是收获良多。
-
一、理论
-
1、什么是starter
-
2、项目命名带starter和不带的区别
-
二、实现一个自己的Starter
-
1、sayhello-spring-boot-starter
-
2、xdx-test
-
3、其它
-
三、简单看一下spring-boot-starter的自动注入
-
四、源码获取
一、理论
1、什么是starter
我们在进行Java开发的时候要引入各种依赖,比如JDBC、MySQL、Redis、MyBatis 等等,但各种依赖包本身又各自依赖了自己的依赖,在很久以前没有各种starter的时候,我们要频繁的解决各种依赖包冲突的问题,这是件很头疼的事。
为了解决这种依赖冲突问题,就出现了各种 spring-boot-starter-xxxx 、xxxx-spring-boot-starter 我们只需要导入对应的starter,并且版本和SpringBoot版本一致就不会出现依赖冲突的问题。
我们去看各种starter的pom文件就会发现,其实所谓的各种starter也是引入了最基本的依赖(比如 mybatis-plus-boot-starter 里面就引入了 mybatis-plus)然后再做一些基本的配置注入就完成了(这个自动配置就是starter的核心)。
注:spring-boot-starter-xxxx 这是官方提供的命名规则,xxxx-spring-boot-starter这是非官方提供的。
2、项目命名带starter和不带的区别
我在学习starter的时候有一个问题,比如我在pom里面引入了下面两个依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.7</version>
</dependency>
它们俩有啥区别呢?反正我们在打包的时候都是 mvn install
,当然我们不能说它们的功能不一样,这毫无意义。
什么时候取名需要带上这个starter呢,首先这个取名你随意,其次我觉得如果你是要和整合SpringBoot的时候可以带上这个starter,并且你整合的SpringBoot版本也要和你定义的版本一致。
二、实现一个自己的Starter
我在很早之前就背了一个面试题,并在很多次面试中也被问到了,下面是问题与我的答案(答案不一定对)
Spring Boot 自动配置原理是什么?
注解 @EnableAutoConfiguration, @Configuration, @ConditionalOnClass 就是自动配置的核心,首先它的是一个配置文件,其次根据类路径下是否有这个类去自动配置。
虽然我很早之前就会背了,但一直不得其中意,下面跟着我来实现一个自己的starter你就会理解:什么是自动配置,以及它的原理是什么
我们的代码分为两部分
-
sayhello-spring-boot-starter 我们今天的主角,自己的starter -
xdx-test 一个测试starter的项目
1、sayhello-spring-boot-starter

1-1、pom.xml
要看一个项目的技术,最快捷的就是去看看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.xdx97.sayhello</groupId>
<artifactId>sayhello-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
1-2、pojo
这里就是简单的实体,它会从配置文件里面读取相应的配置信息,为了代码的简洁就只复制一个
package com.xdx97.sayhello.pojo;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "sayhello.chinese")
public class Chinese {
private String say;
private String city;
public String getSay() {
return say;
}
public void setSay(String say) {
this.say = say;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
1-4、service
这就是我们对外提供的“实用”方法了,可以看到我并没有使用@Service
注解,这个和starter没有关系,只是我单纯的想要控制什么时候注入这个bean,后面会详细说明。
package com.xdx97.sayhello.service;
import com.xdx97.sayhello.pojo.Chinese;
import org.springframework.beans.factory.annotation.Autowired;
public class ChineseService {
@Autowired
private Chinese chinese;
public String show() {
return "我说 " + chinese.getSay() + "我来自 " + chinese.getCity();
}
}
1-5、spring-configuration-metadata.json
平时我们在yml文件里面写配置的时候会有提示,有时候我们没有配置,也会有默认值,全都来自这个配置文件
{
"properties": [
{
"name": "sayhello.chinese.chineseService",
"type": "java.lang.String",
"description": "desc",
"defaultValue": "false"
},
{
"name": "sayhello.chinese.say",
"type": "java.lang.String",
"description": "desc",
"defaultValue": "汉语"
},
{
"name": "sayhello.chinese.city",
"type": "java.lang.String",
"description": "desc",
"defaultValue": "中国"
},
{
"name": "sayhello.english.englishService",
"type": "java.lang.String",
"description": "desc",
"defaultValue": "false"
},
{
"name": "sayhello.english.speak",
"type": "java.lang.String",
"description": "desc",
"defaultValue": "english"
},
{
"name": "sayhello.english.eat",
"type": "java.lang.String",
"description": "desc",
"defaultValue": "eat"
}
]
}
1-6、spring.factories
这个就是自动配置的核心配置文件,告诉我们的系统我们需要自动配置的文件所在位置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.xdx97.sayhello.AutoConfigurationSayHello
1-7、AutoConfigurationSayHello
这个就是我们最终要自动配置的bean了
package com.xdx97.sayhello;
import com.xdx97.sayhello.service.ChineseService;
import com.xdx97.sayhello.service.EnglishService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 表示我们这个是一个javaconfig配置
@Configuration
public class AutoConfigurationSayHello {
@Bean
// 去配置文件里面读取sayhello.chinese.chineseService 的值,如果等于 havingValue 就注入
@ConditionalOnProperty(prefix = "sayhello.chinese", name = "chineseService", havingValue = "true")
// 它会保证你的bean只有一个,即你的实例只有一个
@ConditionalOnMissingBean(ChineseService.class)
public ChineseService chineseService(){
return new ChineseService();
}
@Bean
@ConditionalOnProperty(prefix = "sayhello.english", name = "englishService", havingValue = "true")
@ConditionalOnMissingBean(EnglishService.class)
public EnglishService englishService(){
return new EnglishService();
}
}
注1:这里我想让使用这个starter的人手动控制这个bean是否需要初始化,所以没有使用注解@ConditionalOnClass
而是使用ConditionalOnProperty
注2:在前面我们说到我们会自动配置的核心是三个注解,现在还少了一个@EnableAutoConfiguration
那是因为我们的这个starter并不是在当前项目运行,而是在别的项目中运行,而我们的SpringBoot项目都有一个启用注解@SpringBootApplication
这个里面就包含了上述的这个。

1-8、打包
这里我只是在本地使用这个starter所以我使用 mvn install
把它安装到本地仓库,如果你需要使用远程仓库,可以先配置maven远程仓库地址,然后使用 mvn deploy
2、xdx-test

这就是一个普通的项目,只有一个要求,它的maven仓库和上面这个starter是一个即可。
2-1、pom
因为在starter里面已经引入了springboot,所以我这里可以不用引入直接使用
<?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>org.example</groupId>
<artifactId>xdx-test</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.xdx97.sayhello</groupId>
<artifactId>sayhello-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
2-2、controller
这就是一个简单的controller
package com.xdx97.controller;
import com.xdx97.sayhello.service.ChineseService;
import com.xdx97.sayhello.service.EnglishService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Autowired
private ChineseService chineseService;
@Autowired
private EnglishService englishService;
@GetMapping("/funTestOne")
public String funTestOne(){
return chineseService.show();
}
@GetMapping("/funTestTwo")
public String funTestTwo(){
return englishService.show();
}
}
2-3、application.yml
这个配置文件,算是我们的一个核心了,我们通过它来控制我们的实体bean是否注入,同时也用它来设置属性值
server:
port: 8888
sayhello:
chinese:
# 只有为true的时候才注入这个bean
chineseService: true
say: 我是小道仙
english:
englishService: true
3、其它
项目启动就可以运行了,结果就不展示了,很简单。
3-1、
这里因为我想使用配置文件来控制bean的注入,所以我没有在 ChineseService.class
上面使用 @Service
注解,如果使用了,那么我们的配置文件就不生效了,就一定可以注入了。
这个思路来源于我老大写的一个starter,只不过他那个的bean是openfeign,倒不是使用的new,而是基于jdk代理。
3-2、
starter的核心其实就是自动注入,也就是几个配置文件和注解,重要的是我们要控制bean在什么调节下进行注入,相对应的就有很多相关注解了
太多了也记不住,只要记住是在xx调节下进行bean的注入,用到的时候再去搜索一下

三、简单看一下spring-boot-starter的自动注入
只要我们的代码里面引入了spring-boot-starter就可以看到如下的依赖

我们可以去spring.factories
里面找到我们想要了解的starter在自动配置的时候做了什么操作
四、源码获取
公众号回复关键字获取源码:xdx-spring-boot-starter
原文始发于微信公众号(小道仙97):手把手教你如何自定义spring-boot-starter,附视频讲解
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/41319.html