欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

手把手教你如何自定义spring-boot-starter,附视频讲解

时间:2023-06-19

视频讲解地址 https://www.bilibili.com/video/BV18b4y147YV/


之所以想要学习这个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里面引入了下面两个依赖

com.baomidou mybatis-plus-boot-starter ${mybatis-plus.version} cn.hutool hutool-all 5.3.7

它们俩有啥区别呢?反正我们在打包的时候都是 mvn install ,当然我们不能说它们的功能不一样,这毫无意义。

什么时候取名需要带上这个starter呢,首先这个取名你随意,其次我觉得如果你是要和整合SpringBoot的时候可以带上这个starter,并且你整合的SpringBoot版本也要和你定义的版本一致。


二、实现一个自己的Starter

我在很早之前就背了一个面试题,并在很多次面试中也被问到了,下面是问题与我的答案(答案不一定对)

Spring Boot 自动配置原理是什么?

注解 @EnableAutoConfiguration, @Configuration, @ConditionalOnClass 就是自动配置的核心,首先它得是一个配置文件,其次根据类路径下是否有这个类去自动配置。

虽然我很早之前就会背了,但一直不得其中意,下面跟着我来实现一个自己的starter你就会理解:什么是自动配置,以及它的原理是什么


我们的代码分为两部分

sayhello-spring-boot-starter 我们今天的主角,自己的starterxdx-test 一个测试starter的项目
1、sayhello-spring-boot-starter 1-1、pom.xml

要看一个项目的技术,最快捷的就是去看看pom里面引入了哪些依赖

<?xml version="1.0" encoding="UTF-8"?> 4.0.0 com.xdx97.sayhello sayhello-spring-boot-starter 1.0-SNAPSHOT yyyyMMddHHmmss 8 8 org.springframework.boot spring-boot-dependencies 2.2.1.RELEASE pom import org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-configuration-processor true


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配置@Configurationpublic 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"?> 4.0.0 org.example xdx-test 1.0-SNAPSHOT com.xdx97.sayhello sayhello-spring-boot-starter 1.0-SNAPSHOT 8 8


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;@RestControllerpublic 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: 8888sayhello: 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在自动配置的时候做了什么操作


四、源码获取

如果对你有帮助,可以关注我的微信公众号一起成长:小道仙97

回复关键字获取源码:xdx-spring-boot-starter

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。