Java 一個特殊的類 ServiceLoader<S> 詳解

  ServiceLoader與ClassLoader是Java中2個即相互區別又相互聯繫的加載器.JVM利用ClassLoader將類載入內存,這是一個類聲明週期的第一步(一個java類的完整的生命週期會經歷加載、連接、初始化、使用、和卸載五個階段,當然也有在加載或者連接之後沒有被初始化就直接被使用的情況)。詳情請參閱:詳解Java類的生命週期

ServiceLoader又是什麼呢?ServiceLoader:一個簡單的服務提供者加載設施。服務 是一個熟知的接口和類(通常爲抽象類)集合。服務提供者 是服務的特定實現。提供者中的類通常實現接口,並子類化在服務本身中定義的子類。服務提供者可以以擴展的形式安裝在 Java 平臺的實現中,也就是將 jar 文件放入任意常用的擴展目錄中。也可通過將提供者加入應用程序類路徑,或者通過其他某些特定於平臺的方式使其可用。……唯一強制要求的是,提供者類必須具有不帶參數的構造方法,以便它們可以在加載中被實例化。

通過在資源目錄META-INF/services中放置提供者配置文件 來標識服務提供者。文件名稱是服務類型的完全限定二進制名稱。該文件包含一個具體提供者類的完全限定二進制名稱列表,每行一個。忽略各名稱周圍的空格、製表符和空行。註釋字符爲'#'('\u0023', NUMBER SIGN);忽略每行第一個註釋字符後面的所有字符。文件必須使用 UTF-8 編碼。 

以延遲方式查找和實例化提供者,也就是說根據需要進行。服務加載器維護到目前爲止已經加載的提供者緩存。每次調用 iterator 方法返回一個迭代器,它首先按照實例化順序生成緩存的所有元素,然後以延遲方式查找和實例化所有剩餘的提供者,依次將每個提供者添加到緩存。可以通過 reload 方法清除緩存。

    首先這個類是 final 不能繼承的。經常我們會有一個接口許多實現類,比如: UserDao接口有UserDaoImpl1 、UserDaoImpl2 ....等多個實現。這時候我們只能自己new,但是有了ServiceLoader<S>就非常方便,他會幫我們把實現類放入一個集合方便遍歷 。但是這又有什麼用呢,這個配合命令模式就有大用了:

    首先在src文件夾下面創建一個META-INF文件夾裏面再創建一個services文件夾裏面放着一個你接口的全類名 的文件 比如 org.web.UserDao  

而文件裏面放着這個接口的實現類 比如 org.web.UserDaoImpl1  org.web.UserDaoImpl2

然後一句代碼就OK了 

ServiceLoader<UserDao>list=ServiceLoader.load(UserDao.class); 

然後就可以遍歷list了 

接下來介紹一下這個ServiceLoader的常用用途

比如我們要判斷傳過來來的值是什麼類型的

if(a == 1){
  //處理的事
}
else if(a == 2){
  //處理的事
}else if(a == 2){
  //處理的事
} 

這樣的話以後多一種情況就多一種else if   不利於擴展

所以可以把每個if 做成命令模式

首先創建一個藉口 Interface 

public interface inte{
  //判斷是否用這個實現類的解決方案
  public boolean is(int num);
  //解決方案
  public void result();
} 

然後創建2個實現類

public class inteImpl1 implements inte{
  public boolean is(int num){
    //代替了多重if
    if(num == 1)
      return true;
    return false;
  }
  public void result(){
    //這裏是 1的解決方案
  }
} 
public class inteImpl2 implements inte{
  
 public boolean is(int num){
    //代替了多重if
    if(num == 2)
      return true;
    return false;
  }
  public void result(){
    //這裏是 2的解決方案
  }
} 

寫好services裏面的對應接口和實現類的全類名:

xx.xx.inteImpl1
xx.xx.inteImpl2 


然後就可以使用了:

ServiceLoader<Inte> list=ServiceLoader.load(Inte.class);  
for(Inte in :list){
  if(in.is(1)){
    in.result();
  }
} 

這樣以後要擴展就多寫一個實現類,多加一項配置,更好的體現了面向對象的思想。


參考:http://blog.csdn.net/lmh12506/article/details/50428860

    http://www.cnblogs.com/nimendezaige/p/4866468.html




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章