一、springboot 中的spi机制什么是spi呢,全称是service provider interface。简单翻译的话,就是服务提供者接口,是一种寻找服务实现的机制。
其实就是一个规范定义、或者说是实现的标准。
用生活中的例子说就是,你买了一台小米的手机。
但是你用的充电器并不一定非要是小米充电器,你可以拿其他厂商的充电器来进行充电,只要满足协议、端口等要求,那么就是可以充电的。这也是一种热拔插的思想,并不是固定死的。
换成代码来说也是一样的,我定义了一个接口,但是不想固定死具体的实现类,因为那样如果要更换实现类就要改动源代码,这往往是不合适的。
那么我也可以定义一个规范,在之后需要更换实现类或增加其他实现类时,遵守这个规范,我也可以动态的去发现这些实现类。
换在springboot中,就是现在的springboot这个平台定义了一些规范和标准,我现在想要让springboot平台接纳我。
我该如何做呢?
很简单,按照它的标准和规范做事。
springboot在启动的时候,会扫描所有jar包resource/meta-inf/spring.factories文件,依据类的全限定名,利用反射机制将bean装载进容器中。
二、自定义 starter说一说我的小实践:
在这个 starter 中,实现
发送短线的template
对象存储的template
的自动装配~
大致就是四步:
用于映射配置文件中的配置的类xxxxproperties
用于操作xxxx的接口和客户端等等,如本文中的osstemplate
自动配置类xxxxautoconfiguration ,并且向容器中注入xxxxtemplate
在spring.factories中将xxxxautoconfiguration添加进enableautoconfiguration的vaule集合中
对象存储我用的是阿里云的oss,里面的配置都是可以用的, 短信的话,就是个模拟的啦~,勿怪啦
2.1、准备一个maven项目删除src目录,
然后再创建两个 maven项目(我个人习惯,习惯创建空maven项目,实际上创建springboot项目也是一样)
最外层的pom.xml
<parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>2.5.2</version> <relativepath/> </parent> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupid>org.projectlombok</groupid> <artifactid>lombok</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-test</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-configuration-processor</artifactid> <optional>true</optional> </dependency> </dependencies>
2.2、准备properties类就是用来映射配置文件的~
/** * @author ning zaichun */ @data @configurationproperties(prefix = "nzc.oss") public class ossproperties { private string accesskey; private string secret; private string bucketname; private string url; private string endpoint; }
@data @configurationproperties(prefix = "nzc.sms") public class smsproperties { private string name; }
2.3、准备要注入的类就是我们最后要通过自动装配注入进springboot操作的类
我这里分别是osstemplate 和 smstemplate
/** * @author ning zaichun */ public class osstemplate { private ossproperties ossproperties; public osstemplate(ossproperties ossproperties) { this.ossproperties = ossproperties; } public string test() { system.out.println(ossproperties.getbucketname()); return "test"; } public string upload(string filename, inputstream is) { // yourendpoint填写bucket所在地域对应的endpoint。以华东1(杭州)为例,endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。 string endpoint = ossproperties.getendpoint(); // 阿里云主账号accesskey拥有所有api的访问权限,风险很高。强烈建议您创建并使用ram账号进行api访问或日常运维,请登录 https://ram.console.aliyun.com 创建ram账号。 string accesskeyid = ossproperties.getaccesskey(); string accesskeysecret = ossproperties.getsecret(); // 创建ossclient实例。 oss ossclient = new ossclientbuilder().build(endpoint, accesskeyid, accesskeysecret); string storepath = new simpledateformat("yyyy/mm/dd").format(new date()) + "/" + uuid.randomuuid() + filename.substring(filename.lastindexof(".")); system.out.println(storepath); // 依次填写bucket名称(例如examplebucket)和object完整路径(例如exampledir/exampleobject.txt)。object完整路径中不能包含bucket名称。 ossclient.putobject(ossproperties.getbucketname(), storepath, is); string url = ossproperties.geturl() + storepath; // 关闭ossclient。 ossclient.shutdown(); return url + "#" + storepath; } public void remove(string fileurl) { // yourendpoint填写bucket所在地域对应的endpoint。以华东1(杭州)为例,endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。 string endpoint = ossproperties.getendpoint(); // 阿里云账号accesskey拥有所有api的访问权限,风险很高。强烈建议您创建并使用ram用户进行api访问或日常运维,请登录ram控制台创建ram用户。 string accesskeyid = ossproperties.getaccesskey(); string accesskeysecret = ossproperties.getsecret(); // 填写bucket名称。 string bucketname = ossproperties.getbucketname(); // 填写文件完整路径。文件完整路径中不能包含bucket名称。 //2022/01/21/f0870eb3-4714-4fae-9fc3-35e72202f193.jpg string objectname = fileurl; // 创建ossclient实例。 oss ossclient = new ossclientbuilder().build(endpoint, accesskeyid, accesskeysecret); // 删除文件或目录。如果要删除目录,目录必须为空。 ossclient.deleteobject(bucketname, objectname); // 关闭ossclient。 ossclient.shutdown(); } }
public class smstemplate { private smsproperties properties; public smstemplate(smsproperties properties) { this.properties = properties; } public void sendsms(string mobile, string code){ system.out.println(properties.getname()+"=="+mobile+"===="+code); } }
2.4、autoconfiguration @enableconfigurationproperties({ smsproperties.class, ossproperties.class }) public class commonautoconfig { @bean public smstemplate smstemplate(smsproperties smsproperties){ return new smstemplate(smsproperties); } @bean public osstemplate osstemplate(ossproperties ossproperties){ return new osstemplate(ossproperties); } }
2.5、编写spring.factories在resource目录下,创建一个meta-inf文件夹,
在meta-inf文件夹下创建一个spring.factories文件
内容是
org.springframework.boot.autoconfigure.enableautoconfiguration=\ com.nzc.commonautoconfig
如果有多个就是:
org.springframework.boot.autoconfigure.enableautoconfiguration=\ com.nzc.commonautoconfig \ com.xxx.xxx
到这一步之后,我们将这个项目,达成jar包,然后在要使用的项目中进行引入。
2.6、应用测试1、创建一个springboot 的启动类,有启动类才能进行测试,不然没上下文环境~
2、编写配置文件
spring: application: name: app-server nzc: sms: name: ningzaichun oss: accesskey: xxx secret: xxx endpoint: oss-cn-shenzhen.aliyuncs.com bucketname: xxx url: xxx
将oss的配置修改正确是可以用的~
编写测试类:
@runwith(springrunner.class) @springboottest(classes = appserverapplication.class) public class templatetest { @autowired private osstemplate osstemplate; @test public void testoss(){ string s = osstemplate.test(); system.out.println(s); } @test public void testupload(){ try { file file = new file("d:\evectionflow01.png"); inputstream inputstream = new fileinputstream(file); osstemplate.upload("123.jpg",inputstream); } catch (filenotfoundexception e) { e.printstacktrace(); } } @autowired private smstemplate smstemplate; @test public void testsendsms(){ smstemplate.sendsms("17670090715","123456"); } }
证明是可以使用的~
以上就是springboot spi机制和自定义starter怎么实现的详细内容。