Java之SPI机制
之前開阿里的HSF框架,里面用到了Java的SPI機制,今天閑暇的時候去了解了一下,通過寫博客來記錄一下
SPI的全名為Service Provider Interface,我對于該機制的理解是為接口尋找服務實現類。現在公司的系統都是進行了模塊的劃分,系統抽象為多個模塊,往往有很多不同的實現方案,比如日志模塊的方案,xml解析模塊、jdbc模塊的方案等。面向的對象的設計里,我們一般推薦模塊之間基于接口編程,模塊之間不對實現類進行硬編碼。一旦代碼里涉及具體的實現類,就違反了可拔插的原則,如果需要替換一種實現,就需要修改代碼。于是就有了SPI這種服務發現機制。
java spi的具體使用如下??:
當服務的提供者,提供了服務接口的一種實現之后,在jar包的META-INF/services/目錄里同時創建一個以服務接口命名的文件。該文件里就是實現該服務接口的具體實現類。而當外部程序裝配這個模塊的時候,就能通過該jar包META-INF/services/里的配置文件找到具體的實現類名,并裝載實例化,完成模塊的注入。?
基于這樣一個約定就能很好的找到服務接口的實現類,而不需要再代碼里制定。
jdk提供服務實現查找的一個工具類:java.util.ServiceLoader
參考案例:
項目文件結構:
參考代碼:
Developer.javapackage cn.edu.knowledge.spi;public interface Developer {public String getPrograme();} JavaDeveloper.javapackage cn.edu.knowledge.spi;public class JavaDeveloper implements Developer {@Overridepublic String getPrograme() {return "Java";} }META-INF\services文件下的cn.edu.knowledge.spi.Developer文件內容是服務類的全限命名:
cn.edu.knowledge.spi.JavaDeveloper將文件導出為jar包,新建一個項目,在項目中導入該jar,下面的測試類的代碼
Test.javaimport java.util.ServiceLoader; import cn.edu.knowledge.spi.Developer; public class Test {public ServiceLoader<Developer> serviceloader = ServiceLoader.load(Developer.class);public static void main(String[] arg) {Test devClient = new Test();Developer dev = devClient.getDeveloper();System.out.println(dev.getPrograme());}private Developer getDeveloper() {Developer lastdev = null;for (Developer dev : serviceloader) {System.out.println("out." + dev.getPrograme());lastdev = dev;}if(lastdev==null)System.out.println("why...");return lastdev;}}我們在開發中都有用到SPI機制,但是我們沒有意識到比如:
1.common-logging
apache最早提供的日志的門面接口。只有接口,沒有實現。具體方案由各提供商實現,發現日志提供商是通過掃描??META-INF/services/org.apache.commons.logging.LogFactory?配置文件,通過讀取該文件的內容找到日志提工商實現類。只要我們的日志實現里包含了這個文件,并在文件里制定???LogFactory工廠接口的實現類即可。
2.jdbc
jdbc4.0以前,開發人員還需要基于Class.forName("xxx")的方式來裝載驅動,jdbc4也基于spi的機制來發現驅動提供商了,可以通過META-INF/services/java.sql.Driver文件里指定實現類的方式來暴露驅動提供者。
學習到的知識:面向接口編程可以實現接口和實現的分離,這樣做的最大好處就是能夠在客戶端未知的情況下修改實現代碼。那么什么時候應該抽象出Java接口呢?一種是用在層和層之問的調用。層和層之間是最忌諱耦合度過高或是改變過于頻繁。設計優秀的接口能夠解決這個問題。另一種是用在那些不穩定的部分上。如果某些需求的變化性很大,那么定義接口也是一種解決之道。設計良好的接口就像是我們日常使用的萬用插座一樣,不論插頭如何變化,都可以使用。
總結
以上是生活随笔為你收集整理的Java之SPI机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 卧室窗帘哪种颜色有助于睡眠?
- 下一篇: java整合apollo(一)