<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Java SPI提供了一種為某個介面尋找服務實現的機制。有點類似IOC的思想,就是將裝配的控制權移到程式之外,在模組化設計中這個機制尤其重要,SPI的核心思想就是解耦。
SPI全稱Service Provider Interface,是Java提供的一套用來被第三方實現或者擴充套件的API,它可以用來啟用框架擴充套件和替換元件。Java SPI 實際上是“基於介面的程式設計+策略模式+組態檔”組合實現的動態載入機制。在物件導向的程式設計與設計中,一般推薦模組之間要基於介面程式設計,模組之間不對實現類進行寫死,一旦程式碼裡涉及了具體的實現類,就違反了可拔插的原則,如果需要替換另外一種實現,就需要修改程式碼。
使用Java SPI機制的優勢是實現解耦,使得第三方服務模組的裝配控制的邏輯與呼叫者的業務程式碼分離,而不是耦合在一起,應用程式可以根據實際業務情況啟用框架擴充套件或替換框架元件,常見的場景如下:
(1). JDBC載入不同型別的驅動
(2). SLF4J對Log4j/Logback的支援
…
(1). 服務提供者提供介面的具體實現,在JAVA包的META-INF/services目錄下建立一個以“介面全限定名”為命名的檔案,內容為實現類的全限定名;
(2). 介面具體實現類所在的JAR包需要放在主程式的CLASSPATH中;
(3). 主程式通過java.util.ServiceLoder動態載入具體的實現模組,它通過掃描META-INF/services目錄下的組態檔,找到具體實現類並把它載入到JVM中;
(4). SPI的實現類必須攜帶一個不帶引數的建構函式。
(1). 提供某種功能的介面(SLF4J 提供了一組介面類)
(2). 提供某種功能介面的具體實現(每個具體的實現需要包含:META-INF/services目錄下建立一個以“介面全限定名”為命名的檔案,內容為實現類的全限定名。Log4j/Logback提供了具體的實現)
(3). 提供發現和載入CLASSPATH中所有的介面具體實現的物件
(4). 使用者端(介面的使用者)
關於JAVA SPI詳細的介紹請看:JAVA - SPI機制使用詳解(一)
主要角色有:介面、多個實現類以及測試使用者端,在每個實現類中需要建立資訊檔案:resources/META-INF/services/介面全限定名一致的檔案。介面、多個實現類以及使用者端分別在不同的MODULE中。
①. 介面:
package com.hadoopx.javax.spi; public interface Coder { public String write(); }
②. 第一個實現類:
package com.hadoopx.javax.spi; public class Javaer implements Coder { public String write() { return "I'M JAVA CODER, USE JAVA TO WRITE EVERYTHING."; } } 建立資訊說明檔案:resources/META-INF/services/com.hadoopx.javax.spi.Coder, 裡面的內容為:com.hadoopx.javax.spi.Javaer
③. 第二個實現類:
package com.hadoopx.javax.spi; public class Rubyer implements Coder { public String write() { return "I'M RUBY CODER, USE RUBY TO WRITE EVERYTHING."; } } 建立資訊說明檔案:resources/META-INF/services/com.hadoopx.javax.spi.Coder, 裡面的內容為:com.hadoopx.javax.spi.Rubyer
④. 使用者端:
新增依賴: <dependencies> <dependency> <groupId>com.hadoopx</groupId> <artifactId>javax-spi001-javaer</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.hadoopx</groupId> <artifactId>javax-spi001-rubyer</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
使用者端程式碼: package com.hadoopx.javax.spi; public class MyTest { public static void main(String[] args) { ServiceLoader<Coder> s = ServiceLoader.load(Coder.class); Iterator<Coder> iterator = s.iterator(); while (iterator.hasNext()) { Coder lang = iterator.next(); String content = lang.write(); System.out.println(content); } } }
輸出結果為:
I'M JAVA CODER, USE JAVA TO WRITE EVERYTHING.
I'M RUBY CODER, USE RUBY TO WRITE EVERYTHING.
在實際的使用過程中,需要指定不同的型別來建立不同的實現類範例。
注意: 在每個實現類中不需要建立資訊檔案。
①. 介面:
package com.hadoopx.javax.spi; public interface Coder { public String write(); }
②. 第一個實現類:
package com.hadoopx.javax.spi; @Service @Primary public class Javaer implements Coder { public String write() { return "I'M JAVA CODER, USE JAVA TO WRITE EVERYTHING."; } }
③. 第二個實現類:
package com.hadoopx.javax.spi; @Service public class Rubyer implements Coder { public String write() { return "I'M RUBY CODER, USE RUBY TO WRITE EVERYTHING."; } }
④. 使用者端一:
新增依賴: <dependencies> <dependency> <groupId>com.hadoopx</groupId> <artifactId>javax-spi002-javaer</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.hadoopx</groupId> <artifactId>javax-spi002-rubyer</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
使用者端程式碼: @RestController @RequestMapping("/t") @Api(value = "測試服務", description = "該服務僅僅用於完成驗證、學習和測試") public class TestController { // 切換不同的服務 @Autowired @Qualifier("javaer") private Coder coder; @ApiOperation(value = "測試", notes = "基於SPRING BOOT實現的JAVA SPI機制的DEMO") @GetMapping("/spi") public String test() { System.out.println(coder.write()); return "ok"; } }
輸出結果為:
I'M JAVA CODER, USE JAVA TO WRITE EVERYTHING.
⑤. 使用者端二:
有時會根據不同的情況,呼叫不同服務的方法,所以在使用者端中需要多增加下面這個檔案:
@Service public class CoderContext { // 通過 @Autowired 把Coder所有的實現類注入到map(coders)中. // Spring會查詢應用的上下文裡型別為Coder的Bean, 並把查詢到的Bean注入到Map<String, Coder> 或者 List<Coder>中 @Autowired Map<String, Coder> coders; public Coder getCoder(String key){ return coders.get(key); } }
使用者端程式碼: @RestController @RequestMapping("/t") @Api(value = "測試服務", description = "該服務僅僅用於完成驗證、學習和測試") public class TestController { @Autowired private CoderContext coderContext; @ApiOperation(value = "測試", notes = "基於SPRING BOOT實現的JAVA SPI機制的DEMO") @GetMapping("/spi") public String test(String type) { System.out.println(coderContext.getCoder(type).write()); return "ok"; } }
到此這篇關於JAVA SPI機制詳解使用方法的文章就介紹到這了,更多相關JAVA SPI機制內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45