SpringBoot?SPI?機制和實現(xiàn)自定義?starter
前言
實現(xiàn)starter,其實就是SpringBoot的自動裝配原理的一個實踐,以前我也寫過SpringBoot的自動狀態(tài)原理的文章,文章鏈接
細心認真對待,沒有什么是很難的。
一、SpringBoot 中的SPI機制
什么是spi呢,全稱是Service Provider Interface
。簡單翻譯的話,就是服務(wù)提供者接口,是一種尋找服務(wù)實現(xiàn)的機制。
其實就是一個規(guī)范定義、或者說是實現(xiàn)的標準。
用生活中的例子說就是,你買了一臺小米的手機。
但是你用的充電器并不一定非要是小米充電器,你可以拿其他廠商的充電器來進行充電,只要滿足協(xié)議、端口等要求,那么就是可以充電的。這也是一種熱拔插的思想,并不是固定死的。
換成代碼來說也是一樣的,我定義了一個接口,但是不想固定死具體的實現(xiàn)類,因為那樣如果要更換實現(xiàn)類就要改動源代碼,這往往是不合適的。
那么我也可以定義一個規(guī)范,在之后需要更換實現(xiàn)類或增加其他實現(xiàn)類時,遵守這個規(guī)范,我也可以動態(tài)的去發(fā)現(xiàn)這些實現(xiàn)類。
換在SpringBoot中,就是現(xiàn)在的SpringBoot這個平臺定義了一些規(guī)范和標準,我現(xiàn)在想要讓SpringBoot平臺接納我。
我該如何做呢?
很簡單,按照它的標準和規(guī)范做事。
SpringBoot在啟動的時候,會掃描所有jar包resource/META-INF/spring.factories
文件,依據(jù)類的全限定名,利用反射機制將Bean
裝載進容器中。
看完這段話,我想你應(yīng)該對今天的文章應(yīng)該有個大概的理解啦。
二、自定義 starter
說一說我的小實踐:
在這個 starter 中,實現(xiàn)
- 發(fā)送短線的Template
- 對象存儲的Template
的自動裝配~
大致就是四步:
- 用于映射配置文件中的配置的類xxxxProperties
- 用于操作xxxx的接口和客戶端等等,如本文中的OssTemplate
- 自動配置類xxxxAutoConfiguration ,并且向容器中注入xxxxTemplate
- 在spring.factories中將xxxxAutoConfiguration添加進EnableAutoConfiguration的vaule集合中
對象存儲我用的是阿里云的oss,里面的配置都是可以用的, 短信的話,就是個模擬的啦~,勿怪啦
2.1、準備一個Maven項目
刪除src目錄,
然后再創(chuàng)建兩個 Maven項目(我個人習慣,習慣創(chuàng)建空Maven項目,實際上創(chuàng)建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填寫B(tài)ucket所在地域?qū)?yīng)的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。 ? ? ? ? ?String endpoint = ossProperties.getEndpoint(); ? ? ? ? ?// 阿里云主賬號AccessKey擁有所有API的訪問權(quán)限,風險很高。強烈建議您創(chuàng)建并使用RAM賬號進行API訪問或日常運維,請登錄 https://ram.console.aliyun.com 創(chuàng)建RAM賬號。 ? ? ? ? ?String accessKeyId = ossProperties.getAccessKey(); ? ? ? ? ?String accessKeySecret = ossProperties.getSecret(); ? ? ? ? ?// 創(chuàng)建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); ? ? ? ? ?// 依次填寫B(tài)ucket名稱(例如examplebucket)和Object完整路徑(例如exampledir/exampleobject.txt)。Object完整路徑中不能包含Bucket名稱。 ? ? ? ? ?ossClient.putObject(ossProperties.getBucketName(), storePath, is); ? ? ? ? ?String url = ossProperties.getUrl() + storePath; ? ? ? ? ?// 關(guān)閉OSSClient。 ? ? ? ? ?ossClient.shutdown(); ? ? ? ? ?return url + "#" + storePath; ? } ? ? ?public void remove(String fileUrl) { ? ? ? ? ?// yourEndpoint填寫B(tài)ucket所在地域?qū)?yīng)的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。 ? ? ? ? ?String endpoint = ossProperties.getEndpoint(); ? ? ? ? ?// 阿里云賬號AccessKey擁有所有API的訪問權(quán)限,風險很高。強烈建議您創(chuàng)建并使用RAM用戶進行API訪問或日常運維,請登錄RAM控制臺創(chuàng)建RAM用戶。 ? ? ? ? ?String accessKeyId = ossProperties.getAccessKey(); ? ? ? ? ?String accessKeySecret = ossProperties.getSecret(); ? ? ? ? ?// 填寫B(tài)ucket名稱。 ? ? ? ? ?String bucketName = ossProperties.getBucketName(); ? ? ? ? ?// 填寫文件完整路徑。文件完整路徑中不能包含Bucket名稱。 ? ? ? ? ?//2022/01/21/f0870eb3-4714-4fae-9fc3-35e72202f193.jpg ? ? ? ? ?String objectName = fileUrl; ? ? ? ? ?// 創(chuàng)建OSSClient實例。 ? ? ? ? ?OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); ? ? ? ? ?// 刪除文件或目錄。如果要刪除目錄,目錄必須為空。 ? ? ? ? ?ossClient.deleteObject(bucketName, objectName); ? ? ? ? ?// 關(guān)閉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目錄下,創(chuàng)建一個META-INF文件夾,
在META-INF文件夾下創(chuàng)建一個spring.factories文件
內(nèi)容是
?org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ ? com.nzc.CommonAutoConfig
如果有多個就是:
?org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ ? com.nzc.CommonAutoConfig \ ? com.xxx.xxx
到這一步之后,我們將這個項目,達成Jar包,然后在要使用的項目中進行引入。
2.6、應(yīng)用測試
- 1、創(chuàng)建一個SpringBoot 的啟動類,有啟動類才能進行測試,不然沒上下文環(huán)境~
- 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"); ? ? } ?}
證明是可以使用的~
后記
寫得較為簡單,也通俗易懂~,應(yīng)該能明白吧,哈哈,
如果文中有存在錯誤或者是不對的地方,請留下您的評論,我會及時修正,非常感謝!
這次可能是說點廢話,以前我覺得工作三四年的Java開發(fā)工作者,應(yīng)該是會懂很多很多東西。
因為是后端開發(fā)嗎,很多時候不可避免的要接觸到一些其他東西,
運維部署、測試、前端、底層、架構(gòu)
什么的,我說的是接觸,而不是精通~,不要罵我。只是個人看法。
到此這篇關(guān)于SpringBoot SPI 機制和實現(xiàn)自定義 starter的文章就介紹到這了,更多相關(guān)SpringBoot SPI內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
簡析Java中的util.concurrent.Future接口
這篇文章主要介紹了簡析Java中的util.concurrent.Future接口,作者把future歸結(jié)為在未來得到目標對象的占位符,需要的朋友可以參考下2015-07-07SpringBoot實現(xiàn)郵件任務(wù)的步驟詳解
這篇文章主要介紹了SpringBoot實現(xiàn)郵件任務(wù)的步驟詳解,使用Spring Boot實現(xiàn)QQ郵箱發(fā)送郵件具有快速集成、統(tǒng)一的開發(fā)體驗、強大的維護和擴展能力、可靠的送達性和安全性等優(yōu)勢,可以幫助你快速構(gòu)建穩(wěn)定可靠的郵件發(fā)送功能,需要的朋友可以參考下2023-10-10JAVA簡單工廠模式(從現(xiàn)實生活角度理解代碼原理)
本文主要介紹了JAVA簡單工廠模式(從現(xiàn)實生活角度理解代碼原理)的相關(guān)知識。具有很好的參考價值。下面跟著小編一起來看下吧2017-03-03springboot 事件監(jiān)聽的實現(xiàn)方法
這篇文章主要介紹了springboot 事件監(jiān)聽的實現(xiàn)方法,并詳細的介紹了四種監(jiān)聽方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-04-04解決mybatis-generator生成器添加類注釋方法無效的問題
這篇文章主要介紹了解決mybatis-generator生成器添加類注釋方法無效的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07Spring boot中@Conditional和spring boot的自動配置實例詳解
本文通過實例給大家介紹了Spring boot中@Conditional和spring boot的自動配置,需要的朋友可以參考下2018-05-05