看dobbo源碼的時候,有幾個類繞來繞去的,在調用Protocol的導出服務時,怎麼也沒找到在哪兒配置的具體實現,例如Exporter<?> exporter = protocol.export(invoker); 在debug調試時,看protocol的類型是
com.alibaba.dubbo.rpc.Protocol$Adpative,以下:html
經過命名能夠看出,這是屬於com.alibaba.dubbo.rpc.Protocol類的一個內部類,而這個內部類在Protocol類中又沒有定義,真正調用export方法時,調用的真正實現是RegistryProtocol。着實費解,而後去看Protocol這個接口,看到這個接口上有一個@SPI的註解,這個註解是dubbo框架本身定義的註解,忽然間想到Java的SPI,應該是dubbo本身實現了一套spi機制,因而去官方文檔去找了一下,確實有相關闡述。http://dubbo.io/developer-guide/%E6%89%A9%E5%B1%95%E7%82%B9%E5%8A%A0%E8%BD%BD.htmljava
咱們本身寫代碼的時候,這個東西用的比較少,可是在相關的框架中,仍是有一些應用的,例如commos-logging日誌包和新版的數據庫鏈接DriverManager,就用到Java SPI。程序員
爲了能夠實現可插拔的功能,也就是咱們經常使用的接口,上游廠商定義了標準,而具體的實現放在下游廠商中進行實現。各家下游廠商各自獨立實現不一樣的功能。很常見的就是咱們的電腦預留了USB的接口,USB接口就是一個標準,而後各家廠商生產本身的USB接口的鼠標,鍵盤等等其餘外設設備,它們須要符合USB接口的規範,具體的功能由各個生產廠家本身定製,用的時候插上,不用的時候拔掉,SPI(Service Provider Interface)就是基於這種思想的。
不會把硬代碼侵入到接口的定義中,而是把實現放在了外部。數據庫
基於這種思想,爲了方便廣大程序員使用,Java的jdk中實現了SPI機制,具體的類是Java.util.ServiceLoader,針對此機制,因此會有一些咱們使用上的約定,在這個類的文檔中,有對使用的約定的詳細描述,而且oracle文檔中也有闡述(http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html)總結以下:api
實現一個打印機的功能,聲明一個打印機接口,接口中有一個打印方法doPrint,而後oracle
類結構以下:
├─java
│ └─com
│ └─tofuwang
│ └─myrpc
│ └─spi
│ BlackPrinter.java
│ Printer.java
│ PrintMain.java
└─resources
└─META-INF
│services
com.tofuwang.myrpc.spi.Printer
定義一個打印機接口Printer,裏面有一個打印的方法doPrint框架
public interface Printer { public void doPrint(String body); }
有一個黑白打印機的類BlackPrinter,實現了Printer接口ide
public class BlackPrinter implements Printer { @Override public void doPrint(String body) { System.out.println("黑白打印機打印出內容:"+body); } }
調用方式以下,在PrintMain中定義ui
public class PrintMain { public static void main(String[] args) { ServiceLoader<Printer> load = ServiceLoader.load(Printer.class); Iterator<Printer> iterator = load.iterator(); while (iterator.hasNext()){ Printer next = iterator.next(); next.doPrint("社會主義好!"); } } }
在main方法中,並無對黑白打印的顯示調用,可是確實是有黑白打印機的輸出。spa
以上就是一個很是淺顯的SPI使用示例。