【源起Netty 外傳】ServiceLoader詳解

前戲

netty源碼註釋有云:java

...

If a provider class has been installed in a jar file that is
visible to the system class loader, and that jar file contains a
provider-configuration file named
<tt>java.nio.channels.spi.SelectorProvider</tt> in the resource
directory <tt>META-INF/services</tt>, then the first class name
specified in that file is taken.  The class is loaded and
instantiated; if this process fails then an unspecified error is
thrown.

...

不知所云?好吧,重點是,jar文件中在META-INF/services目錄下配置了A屬性,以某種方式能加載到。maven

how can do that? 答曰:ServiceLoaderide

摸索

ServiceLoader直譯爲服務加載器,最終目的是獲取service的impl實現類。正如前文所說,它將加載META-INF/services下的配置文件,來鎖定impl實現類。this

  • 代碼走起

1.首先,要有一個接口netty

//形狀接口
public interface Shape {
    String introduce(); //介紹
}

2.而後,要有該接口的實現類。實現類很簡單,介紹本身的形狀是啥code

//實現類一
public class Circle implements Shape {
    public String introduce() {
        return "圓形";  //言簡意賅的介紹
    }
}
//實現類二
public class Sequare implements Shape {
    static{
        System.out.println("【Sequare】聽說有延時加載,try it..");
    }
    public String introduce() {
        return "方形";
    }
}

眼尖的朋友可能已經注意到了,這裏有個靜態塊,由於資料中有提到ServiceLoader有延時加載的效果。寡人不信,遂驗之……接口

3.配置文件,放在META-INF/servicesci

文件位置:源碼

- src
    -main
        -resources
            - META-INF
                - services
                    - xxxpackage.Shape

文件名:包名.接口名it

文件內容:包名.接口實現類,換行符分隔

xxxpackage.Circle
xxxpackage.Sequare

4.ServiceLoader調用

ServiceLoader<Shape> shapeLoader = ServiceLoader.load(Shape.class);
Iterator<Shape> it = shapeLoader.iterator();
while(it.hasNext()){
    System.out.println("Iterator<Shape> next()方法調用..");
    Shape shape = it.next();
    System.out.printf("what's shape?%s\n",shape.introduce());
}

調用結果:

Iterator<Shape> next()方法調用..
【Sequare】聽說有延時加載,try it..
what's shape?方形

從該結果可看出,在調用it.next()的時候,才真正的加載了Sequare類,確確實實是延時加載。期具體實現依靠ServiceLoader的內部類LazyIterator,感性趣的朋友能夠本身看一下。

總結

  1. ServiceLoader重點在於可跨越jar包獲取impl,這一點筆者經過maven多模塊項目親測ok
  2. 延時加載特性
相關文章
相關標籤/搜索