java SPI

引用:http://www.cnblogs.com/javaee6/p/3714719.htmlhtml

java中的SPI機制

 

1 SPI機制簡介

SPI的全名爲Service Provider Interface.大多數開發人員可能不熟悉,由於這個是針對廠商或者插件的。在java.util.ServiceLoader的文檔裏有比較詳細的介紹。簡單的總結下java spi機制的思想。咱們系統裏抽象的各個模塊,每每有不少不一樣的實現方案,好比日誌模塊的方案,xml解析模塊、jdbc模塊的方案等。面向的對象的設計裏,咱們通常推薦模塊之間基於接口編程,模塊之間不對實現類進行硬編碼。一旦代碼裏涉及具體的實現類,就違反了可拔插的原則,若是須要替換一種實現,就須要修改代碼。爲了實如今模塊裝配的時候能不在程序裏動態指明,這就須要一種服務發現機制。 java spi就是提供這樣的一個機制:爲某個接口尋找服務實現的機制。有點相似IOC的思想,就是將裝配的控制權移到程序以外,在模塊化設計中這個機制尤爲重要。

2 SPI具體約定

java spi的具體約定爲:當服務的提供者,提供了服務接口的一種實現以後,在jar包的META-INF/services/目錄裏同時建立一個以服務接口命名的文件。該文件裏就是實現該服務接口的具體實現類。而當外部程序裝配這個模塊的時候,就能經過該jar包META-INF/services/裏的配置文件找到具體的實現類名,並裝載實例化,完成模塊的注入。 基於這樣一個約定就能很好的找到服務接口的實現類,而不須要再代碼裏制定。jdk提供服務實現查找的一個工具類:java.util.ServiceLoader

3 應用場景

 
  
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文件裏指定實現類的方式來暴露驅動提供者.

4 案例說明

一個內容管理系統有一個搜索模塊。是基於接口編程的。搜索的實現多是基於文件系統的搜索,也多是基於數據庫的搜索

    接口定義以下java

  1. package my.xyz.spi;  
  2. import java.util.List;  
  3. public interface Search {  
  4.    public List serch(String keyword);  
  5. }    

 

     A公司採用文件系統搜索的方式實現了 Search接口,B公司採用了數據庫系統的方式實現了Search接口sql

          A公司實現的類  com.A.spi.impl.FileSearch  數據庫

          B公司實現的類  com.B.spi.impl.DatabaseSearch  apache

     那麼A公司發佈 實現jar包時,則要在jar包中META-INF/services/my.xyz.spi.Search文件中寫下以下內容編程

     com.A.spi.impl.FileSearchide

     那麼B公司發佈 實現jar包時,則要在jar包中META-INF/services/my.xyz.spi.Search文件中寫下以下內容模塊化

  com.B.spi.impl.DatabaseSearch工具

  1. package com.xyz.factory;  
  2. import java.util.Iterator;  
  3. import java.util.ServiceLoader;  
  4. import my.xyz.spi.Search;  
  5. public class SearchFactory {  
  6.     private SearchFactory() {  
  7.     }  
  8.     public static Search newSearch() {  
  9.         Search search = null;  
  10.         ServiceLoader<Search> serviceLoader = ServiceLoader.load(Search.class);  
  11.         Iterator<Search> searchs = serviceLoader.iterator();  
  12.         if (searchs.hasNext()) {  
  13.             search = searchs.next();  
  14.         }  
  15.         return search;  
  16.     }  
  17. }  

 

  1. package my.xyz.test;  
  2. import java.util.Iterator;  
  3. import java.util.ServiceLoader;  
  4. import com.xyz.factory.SearchFactory;  
  5. import my.xyz.spi.Search;  
  6. public class SearchTest {  
  7.     public static void main(String[] args) {  
  8.         Search search = SearchFactory.newSearch();  
  9.         search.serch("java spi test");  
  10.     }  
  11. }  
相關文章
相關標籤/搜索