1.starter背景简介及作用
(1)什么是starter
starter是SpringBoot中的一个新发明,它有效的下降了项目开发过程的复杂程度,对于简化开发操做有着很是好的效果。
starter的理念:starter会把全部用到的依赖都给包含进来,避免了开发者本身去引入依赖所带来的麻烦。须要注意的是不一样的starter是为了解决不一样的依赖,因此它们内部的实现可能会有很大的差别,例如jpa的starter和Redis的starter可能实现就不同,这是由于starter的本质在于synthesize,这是一层在逻辑层面的抽象,也许这种理念有点相似于Docker,由于它们都是在作一个“包装”的操做,若是你知道Docker是为了解决什么问题的,也许你能够用Docker和starter作一个类比。
(2)自定义starter的背景
- 大家应该都用过不少Starter,中间件很多,但也存在很多中间件缺少Starter或者不兼容
- 比如Spring Boot 3.x 版本更新,部分Starter就还没来得及更新,则使用不了
- 实际企业里面技术组长或架构师也会根据项目需求
- 封装自己的项目组的Starter,达到更快开发的项目,且可以统一规范,简化配置
(3)自定义Starter封装规范
- 官方的Starter包规范:spring-boot-starter-xxx
- 自定义Starter包规范:xxx-spring-boot-starter
spring-boot-starter spring-boot-starter-data-jpa spring-boot-starter-data-redis spring-boot-starter-data-mongodb spring-boot-starter-jdbc mybatis-spring-boot-starter mybatis-plus-boot-starter
(4)新版Spring Boot3.X和旧版SpringBoot2.7之前自定义Starter区别
- SpringBoot2.7之前
- META-INF/spring.factories文件里添加
org.springframework.boot.autoconfigure.EnableAutoConfiguration=XXAutoConfiguration
- 关于springboot2.7之前自定义starter我会用另外一篇文章来展示。这里后续会更新哦!
SpringBoot2.7推出新的自动配置
- 在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
- 文件里添加配置类名称,每行包含一个配置类全限定名
- 兼容META-INF/spring.factories方式
- SpringBoot3.x 移除spring.factories
- 移除META-INF/spring.factories方式
- 只支持META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 增加自动配置
2.自定义starter的步骤
- 创建项目 xx-spring-boot-starter
- 添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>3.0.2</version> </dependency>
- 创建配置类
- 创建XXAutoConfiguration类
- 增加Condition条件注解
- 配置AutoConfiguration.imports自动配置类
3.自定义starter案例实战
(1)需求背景
- 现在公司所有的短信发送都集成到消息中心,为了简化各个平台的开发,自定义封装一个sms-starter提供给各个平台使用。
- 自定义一个发短信的sms-starter,starter对接各个三方的短信平台,阿里云、腾讯云、亚马逊云,开发者可以根据配置进行配置 短信的提供方,默认是 阿里云的提供方。
- 如果Spring容器没有对应的bean则创建,有的话则不创建。
- (2)创建SpringBoot3.x项目 sms-spring-boot-starter,添加autoconfigure依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>3.0.2</version> </dependency>
(3)创建配置类,通过 @ConfigurationProperties注解可以绑定application.yml配置文件
- 创建短信运营商的类型枚举类
public enum SmsTypeEnum { //阿里云 ALI_CLOUD("ali"), //腾讯云 TX_CLOUD("tx"), //亚马逊云 YMX_CLOUD("ymx"); private String type; SmsTypeEnum(String ymx) {} }
@ConfigurationProperties(prefix = "sms.server.achieve") public class SmsProperties { /** * 发送短信类型 */ private String type; public String getType() { if(type == null || "".equals(type)){ type = SmsTypeEnum.ALI_YUN.name(); } return type; } public void setType(String type) { this.type = type; } }
(4)创建SmsService接口,封装三个云厂商的发送短信实现。
public interface SmsService { String send(String fromPhone,String toPhone,String content); }
/** * 阿里云SMS实现 * @author lixiang * @date 2023/5/16 09:30 */ @Service("ali") public class AliCloudSmsServiceImpl implements SmsService { @Override public String send(String fromPhone, String toPhone, String content) { System.out.println("------------------当前SMS厂商为阿里云------------------"); System.out.println("----"+fromPhone+" 向 "+toPhone +" 发送了一条短信。"+"----"); System.out.println("短信内容为:"+content); System.out.println("----------------------------------------------------"); return "success"; } }
/** * 腾讯云SMS实现 * @author lixiang * @date 2023/5/16 09:44 */ @Service("tx") public class TxCloudSmsServiceImpl implements SmsService { @Override public String send(String fromPhone, String toPhone, String content) { System.out.println("------------------当前SMS厂商为腾讯云------------------"); System.out.println("----"+fromPhone+" 向 "+toPhone +" 发送了一条短信。"+"----"); System.out.println("短信内容为:"+content); System.out.println("----------------------------------------------------"); return "success"; } }
/** * 亚马逊云SMS实现 * @author lixiang * @date 2023/5/16 09:42 */ @Service("ymx") public class YmxCloudSmsServiceImpl implements SmsService { @Override public String send(String fromPhone, String toPhone, String content) { System.out.println("------------------当前SMS厂商为亚马逊云------------------"); System.out.println("----"+fromPhone+" 向 "+toPhone +" 发送了一条短信。"+"----"); System.out.println("短信内容为:"+content); System.out.println("----------------------------------------------------"); return "success"; } }
(5)定义SmsTemplate用于统一提供服务
/** * @author lixiang * @date 2023/5/16 09:33 */ public class SmsTemplate { @Autowired private SmsProperties smsProperties; @Autowired private ApplicationContext context; public String send(String fromPhone,String toPhone,String content){ //获取云厂商的业务实现类 String type = smsProperties.getType(); SmsService smsService = (SmsService)context.getBean(type); return smsService.send(fromPhone,toPhone,content); } }
(6)定义SmsAutoConfiguration类
/** * @author lixiang * @date 2023/5/16 09:27 */ @AutoConfiguration @ConditionalOnClass(SmsTemplate.class) @EnableConfigurationProperties(value = SmsProperties.class) public class SmsAutoConfiguration { @Bean @ConditionalOnMissingBean public SmsTemplate smsTemplate(){ return new SmsTemplate(); } }
(7)创建imports配置文件,把需要自动装载的类配置上。
- @AutoConfiguration 是spring boot2.7新引入的,自动配置类必须放进下面的文件里才算自动配置类
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.lixiang.config.SmsAutoConfiguration
(8)mvn clean install 打入到本地仓库
4.验证自定义starter
(1)新建项目,注意一定要是springboot3.x版本以上的。
<dependency> <groupId>com.lixiang</groupId> <artifactId>sms-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
(2)创建测试代码
@RestController @RequestMapping("/spring-test") public class TestController { @Autowired private SmsTemplate smsTemplate; @RequestMapping("/sms") public String sms(){ String fromPhone = "15522834580"; String toPhone = "13820345839"; String content = "李祥,李祥,今晚王者峡谷 六点 五缺一,收到请回复,over!"; return smsTemplate.send(fromPhone,toPhone,content); } }
(3)当配置文件不进行配置时,默认走的是阿里云的厂商。
(4)当配置好云厂商时,就会走配置的云厂商
Ok,SpringBoot3.x,自定义starter已经完成啦,后续会更新springboot2.x自定义starter的步骤,因为目前来看,很多企业还在用springboot2.x的版本。