自定义 Spring Boot Starter
一、引言
什么是Spring Boot Starter呢?我们直接来看看官网是怎么介绍的吧。
Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop shop for all the Spring and related technologies that you need without having to hunt through sample code and copy-paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, include the spring-boot-starter-data-jpa dependency in your project.
我们以上述官网的例子来进行说明比如说我们需要在Spring 中适应JPA来操作数据库。在没有springBoot-starter之前,我们需要引入jpa的步骤
通过maven 引入 jdbc 的依赖、以及 jpa 相关的各种依赖
编写jpa相关的配置文件
网上各种查询找资料进行调试,调试的过程对于新手可能会有点奔溃会遇到各种奇奇怪怪的问题,jar包冲突啊,这个jar包下载不下来,缺少某个jar包。
终于在经历千辛万苦,哼次哼次的解决各种问题之后终于把项目跑起来了,然后把这次整合jpa遇到的问题,以及整合的步骤都一一的详细记录下来。方便下次在需要整合jpa的时候直接copy就好了。我们以前在没有starter之前是不是都是这么玩的。这样的缺点是不是也非常显著,比如过程复杂、需要不停的粘贴复制(不过这是程序员经常干的事情了,也不在乎多一两次了)、整合其它组件到自己的项目变的困难,效率低下。
二、SpringBoot Starter 的出现
我们可以看下SpringBoot 现在都为我们提供有哪些starter,这截图了部分starter,更多的请点击https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-starters
- starter的实现:
虽然我们每个组件的starter实现各有差异,但是它们基本上都会使用到两个相同的内容:ConfigurationProperties和AutoConfiguration
。- 因为SpringBoot提倡“「约定大于配置」”这一理念,所以
我们使用ConfigurationProperties来保存我们的配置,并且这些配置都可以有一个默认值,即在我们没有主动覆写原始配置的情况下,默认值就会生效。
- 除此之外,starter的ConfigurationProperties还
使得所有的配置属性被聚集到一个文件中(一般在resources目录下的application.properties),这样我们就告别了Spring项目中XML地狱
。starter的出现帮把我们把各种复杂的配置都封装起来了,让我们真正的可以达到了开箱即用。不仅降低了我们使用它的门槛,并且还大大提高了我们的开发效率。
- 整体逻辑
三、实现自己的 SpringBoot Starter
- 命名规范
在maven中,groupId代表着姓氏,artifactId代表着名字。Spring Boot也是有一个命名的建议的。所以名字是不能够随随便便取得,可以按照官方的建议来取
。
What’s in a nameAll official starters follow a similar naming pattern; spring-boot-starter-*, where * isa particular type of application. This naming structure is intended to help when you need to find a starter. The Maven integration in many IDEs lets you search dependencies by name. For example, with the appropriate Eclipse or STS plugin installed, you can press ctrl-space in the POM editor and type “spring-boot-starter” for a complete list.As explained in the “Creating Your Own Starter” section, thirdparty starters should not start with spring-boot, as it is reserved for official Spring Boot artifacts.Rather, a third-party starter typically starts with the name of the project. For example, a third-party starter project called thirdpartyproject would typically be named thirdpartyproject-spring-boot-starter.
大概意思是:
- 官方的 starter 的命名格式为 spring-boot-starter-{xxxx}比如spring-boot-starter-activemq
- 第三方我们自己的命名格式为{xxxx}-spring-boot-starter。比如mybatis-spring-boot-starter。
- 如果我们忽略这种约定,是不是会显得我们写的东西不够“专业“。
- 自定义一个 Starter
下面我们就来实现一个自定义的发送短信的 starter,命名为sms-spring-boot-starter。
- 编写配置文件匹配类
发短信我们需要配置一些账号信息,不同的短信供应商,账户信息是不一样的,所以我们需要定义一个XXXXProperties 来自动装配这些账户信息。下面我们就以腾讯云和阿里云两家供应商为例;
//配置前缀,区别各个组件的参数
@ConfigurationProperties(prefix = "sms")
@Data
public class SmsProperties {private SmsMessage aliyun = new SmsMessage();private SmsMessage tencent = new SmsMessage();@Datapublic static class SmsMessage{/*** 用户名*/private String userName;/*** 密码*/private String passWord;/*** 秘钥*/private String sign;/****/private String url;@Overridepublic String toString() {return "SmsMessage{" +"userName='" + userName + '\'' +", passWord='" + passWord + '\'' +", sign='" + sign + '\'' +", url='" + url + '\'' +'}';}}
}
- 编写自动配置类
@EnableConfigurationProperties(value = SmsProperties.class)
@Configuration
public class SmsAutoConfiguration {/*** 阿里云发送短信的实现类* @param smsProperties* @return*/@Beanpublic AliyunSmsSenderImpl aliYunSmsSender(SmsProperties smsProperties){return new AliyunSmsSenderImpl(smsProperties.getAliyun());}/*** 腾讯云发送短信的实现类* @param smsProperties* @return*/@Beanpublic TencentSmsSenderImpl tencentSmsSender(SmsProperties smsProperties){return new TencentSmsSenderImpl(smsProperties.getTencent());}
}
- 编写两个业务类便于测试
@ConditionalOnMissingBean({SmsMessage.class})
public class AliyunSmsSenderImpl implements SmsSender{private final SmsMessage smsMessage;public AliyunSmsSenderImpl(SmsMessage smsProperties) {this.smsMessage = smsProperties;}@Overridepublic boolean send(String message) {System.out.println(smsMessage.toString()+"开始发送短信==》短信内容:"+message);return true;}
}
- 让 starter 生效
starter集成应用有两种方式(被动生效和主动生效
):
- 被动生效:
通过SpringBoot的SPI的机制来去加载我们的 starter
我们需要在META-INF下新建一个spring.factories文件key为org.springframework.boot.autoconfigure.EnableAutoConfiguration
, value是我们的SmsAutoConfiguration 全限定名(「记得去除前后的空格,否则会不生效
」)。
- 主动生效:
前提是先注销spring.factories
主动生效在starter组件集成到我们的Spring Boot应用时需要主动声明启用该starter才生效,通过自定义一个@Enable注解然后在把自动配置类通过Import注解引入进来
。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({SmsAutoConfiguration.class})
public @interface EnableSms {}
使用的时候需要在启动类上面开启这个注解即可。
至此,我们的自定义starter已经写好了,接下来就是打包生成starter.jar。下面是工程完整结构:
注意,不是传统的可运行jar项目,所以没有主入口
- pom.xml文件
<?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 https://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.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.cristiano</groupId><artifactId>sms-spring-boot-starter</artifactId><version>0.0.1</version><name>sms-spring-boot-starter</name><description>sms-spring-boot-starter</description><properties><java.version>1.8</java.version></properties><dependencies><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></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><!--安装到仓库后,引用时不出现 BOOT-INF文件夹(会导致找不到相关类)--><configuration><skip>true</skip></configuration></plugin></plugins></build></project>
重点注意:如果maven没有这么配置,那么打包成jar的时候,会出现BOOT-INF文件夹,导致使用模块的时候,找不到类,详细参考这篇文章
<plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><!--安装到仓库后,引用时不出现 BOOT-INF文件夹(会导致找不到相关类)--><configuration><skip>true</skip></configuration></plugin></plugins>
Lifecycle下install就可以将模块引用到本地仓库了
四、测试Starter
- 引用
<dependency><groupId>com.cristiano</groupId><artifactId>sms-spring-boot-starter</artifactId><version>0.0.1</version></dependency>
- 启用
@SpringBootApplication
@EnableSms
public class TeststarterApplication {public static void main(String[] args) {SpringApplication.run(TeststarterApplication.class, args);}
}
- 配置(有提示)
- 测试
至此就结束了么?其实上面的例子加不加@EnableSms,都能正常打印信息
,因为我们在Starter的spring.factories中已经配置了自动配置类,属于被动加载。
五、插拔式starter(基于主动依赖)
- 在SmsAutoConfiguration的原基础上,加上以下注解后,重新install
@EnableConfigurationProperties(value = SmsProperties.class)
@Configuration
public class SmsAutoConfiguration {/*** 阿里云发送短信的实现类* @param smsProperties* @return*/@Bean//表示在EnableSms注解存在的情况下,该bean才会被注册@ConditionalOnBean(annotation = EnableSms.class)public AliyunSmsSenderImpl aliYunSmsSender(SmsProperties smsProperties){return new AliyunSmsSenderImpl(smsProperties.getAliyun());}/*** 腾讯云发送短信的实现类* @param smsProperties* @return*/@Beanpublic TencentSmsSenderImpl tencentSmsSender(SmsProperties smsProperties){return new TencentSmsSenderImpl(smsProperties.getTencent());}
}
- EnableSms
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({SmsAutoConfiguration.class})
public @interface EnableSms {}
- 主配置类
//不使用@EnableSms
@SpringBootApplication
public class TeststarterApplication {public static void main(String[] args) {SpringApplication.run(TeststarterApplication.class, args);}
}
可以看到报错,原因是AliyunSmsSenderImpl
没有注册到bean中,所以使用条件注解可以实现starter的插拔式应用
正式使用
@EnableSms
@SpringBootApplication
public class TeststarterApplication {public static void main(String[] args) {SpringApplication.run(TeststarterApplication.class, args);}
}
//注入AliyunSmsSenderImpl@AutowiredAliyunSmsSenderImpl aliyunSmsSender;public void test(){aliyunSmsSender.send("from aliyun");}
配置
sms:aliyun:pass-word: aauser-name: aaurl: www.aliyun.comsign: alibaba
参考文章
参考文章
自定义 Spring Boot Starter相关推荐
- 快速开发一个自定义 Spring Boot Starter ,希望你也会
来源:http://t.cn/Ai9li9fC 众所周知,Spring Boot由众多Starter组成,随着版本的推移Starter家族成员也与日俱增.在传统Maven项目中通常将一些层.组件拆分为 ...
- 自定义依赖注解无效_最详细的自定义Spring Boot Starter开发教程
1.前言 随着Spring的日渐臃肿,为了简化配置.开箱即用.快速集成,Spring Boot 横空出世.目前已经成为 Java 目前最火热的框架了.平常我们用Spring Boot开发web应用.S ...
- Spring Boot - 手把手教小师妹自定义Spring Boot Starter
文章目录 Pre 自定义starter的套路 步骤 命名规范 官方命名空间 自定义命名空间 实战 创建一个父maven项目:springboot_custome_starter 创建 两个Module ...
- 手把手教你定制标准 Spring Boot starter
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 写在前面 我们每次构建一个 Spring 应用程序时,我 ...
- 一个项目有两个pom_实现一个Spring Boot Starter超简单,读 Starter 源码也不在话下...
Spring Boot 对比 Spring MVC 最大的优点就是使用简单,约定大于配置.不会像之前用 Spring MVC 的时候,时不时被 xml 配置文件搞的晕头转向,冷不防还因为 xml 配置 ...
- 《SpringCloud超级入门》Spring Boot Starter的介绍及使用《七》
目录 Spring Boot Starter项目创建 自动创建客户端 使用 Starter 使用注解开启 Starter 自动构建 使用配置开启 Starter 自动构建 配置 Starter 内容提 ...
- 实现一个 Spring Boot Starter 原来如此简单,读 Starter 源码也不在话下
我是风筝,公众号「古时的风筝」,一个在程序圈混迹多年,主业 Java,另外 Python.React 也玩儿的 6 的斜杠开发者.现已转行程序员鼓励师 Spring Cloud 系列文章已经完成,可以 ...
- 自定义Spring Boot Starters
传统的做法 在没有starter之前,假如我想要在Spring中使用jpa,那我可能需要做以下操作: 在Maven中引入使用的数据库的依赖(即JDBC的jar) 引入jpa的依赖 在xxx.xml中配 ...
- 一个简易上手的短信服务Spring Boot Starter,连傻瓜都会!
作 者:jackieonway 来 源:jianshu.com/u/36510c75d37c 短信服务在用户注册.登录.找回密码等相关操作中,可以让用户使用更加便捷,越来越多的公司都采用短信验证的方式 ...
最新文章
- 关于librtmp接收数据(接收网络电视的数据流)
- 【转】WebSocket初探
- postgresql 远程用户_构建Python pandas基于SSH远程MySQL和PostgreSQL的数据分析
- 优秀!本科生发表Nature论文,直博美国顶尖名校
- 浏览器皮肤_和平精英返场皮肤投票时间是什么时候?投票地址入口介绍-手游资讯...
- 微信公众号之生成带参数的二维码
- vagrant虚拟机网络设置
- 【python】opencv、PIL、gdal读取tif高分遥感影像比较
- 经验| 张家口交通综合运行协调与应急指挥中心建设
- 注册美国iTunes账号步骤(跳过绑定银行卡)
- Html页面点击下载文件
- Windows10没有画图软件的解决方式
- 【毕业设计】stm32智能车牌识别系统 - 单片机 嵌入式
- 要开始写日志了(Live Witer)
- 菜鸟程序员成长之路(七)——2020年,你奋斗了吗?
- python编程100例海绵宝宝-Python_Turtle库画一只派大星
- oracle12c用plsql连不上,PLSQL连接oracle12c
- javascript+css实现走马灯图片轮播器
- 【测试】工艺路线展开Function
- 入门 redux 和 @connect 装饰器
热门文章
- python-map函数
- 借助JVM生日的时机,说说关于JVM你所不知道的那些事
- bootstrap 之下拉多选
- Java中String字符串toString()、String.valueOf()、String强转、+ 的区别
- 1313 质因数分解 2012年NOIP全国联赛普及组
- machine learning (5)---learning rate
- 根据先序和中序序列重建二叉树
- matlab 中imagesc的用法
- 在java 里kv 是什么_consul kv使用介绍
- [云炬创业学笔记]第三章商业创意的发掘与评估测试4