Java SPI - Service Provider Interface

Java SPI_Service Provider Interfacehtml

咱們系統裏抽象的各個模塊,每每有不少不一樣的實現方案,好比日誌模塊的方案,xml解析模塊、jdbc模塊的方案等。面向的對象的設計裏,咱們通常推薦模塊之間基於接口編程,模塊之間不對實現類進行硬編碼。一旦代碼裏涉及具體的實現類,就違反了可拔插的原則,若是須要替換一種實現,就須要修改代碼。 java

 

爲了實如今模塊裝配的時候能不在程序裏動態指明,這就須要一種服務發現機制。java spi就是提供這樣的一個機制:爲某個接口尋找服務實現的機制。有點相似IOC的思想,就是將裝配的控制權移到程序以外,在模塊化設計中這個機制尤爲重要。編程

 

Java SPI的具體約定以下 :當服務的提供者,提供了服務接口的一種實現以後,在jar包的META-INF/services/目錄裏同時建立一個以服務接口命名的文件。該文件裏就是實現該服務接口的具體實現類。而當外部程序裝配這個模塊的時候,就能經過該jar包META-INF/services/裏的配置文件找到具體的實現類名,並裝載實例化,完成模塊的注入。 api

基於這樣一個約定就能很好的找到服務接口的實現類,而不須要再代碼裏制定。jdk提供服務實現查找的一個工具類:java.util.ServiceLoaderoracle

 

示例以下,使用Java SPI機制實現Compatator接口的服務實現。ide

package com.usoft;

/**
 * Created by xinxingegeya on 15/12/29.
 */
public class MyItem {

    private String name;
    private int level;

    public MyItem(String name, int level) {
        this.name = name;
        this.level = level;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    @Override
    public String toString() {
        return "MyItem{" + "level=" + level + ", name='" + name + '\'' + '}';
    }
}

Comparator實現一:模塊化

package com.usoft;

import java.util.Comparator;

/**
 * Created by xinxingegeya on 15/12/29.
 */
public class ComparatorProviderByLevel implements Comparator<MyItem> {
    @Override
    public int compare(MyItem o1, MyItem o2) {
        return o1.getLevel() - o2.getLevel();
    }
}

Comparator實現二:工具

package com.usoft;

import java.util.Comparator;

/**
 * Created by xinxingegeya on 15/12/29.
 */
public class ComparatorProviderByName implements Comparator<MyItem> {
    @Override
    public int compare(MyItem o1, MyItem o2) {
        return o1.getName().compareTo(o2.getName());
    }
}

classpath路徑下的META-INF/services路徑下創建以接口爲名的文件,java.util.Comparatorthis

#爲註釋編碼

#com.usoft.ComparatorProviderByName
com.usoft.ComparatorProviderByLevel

Main方法,

package com.usoft;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ServiceLoader;

/**
 * Created by xinxingegeya on 15/12/29.
 */
public class Main {

    private static ServiceLoader<Comparator> serviceLoader = ServiceLoader
        .load(Comparator.class, Thread.currentThread().getContextClassLoader());

    public static void main(String args[]) {
        List<MyItem> myList = new ArrayList<>();
        myList.add(new MyItem("c", 2));
        myList.add(new MyItem("a", 7));
        myList.add(new MyItem("d", 4));
        myList.add(new MyItem("b", 5));
//        Collections.sort(myList, new Comparator<MyItem>() {
//            @Override
//            public int compare(MyItem o1, MyItem o2) {
//                return o1.getLevel() - o2.getLevel();
//            }
//        });

        Collections.sort(myList, getComparator());
        showMyList(myList);

    }

    private static void showMyList(List<MyItem> list) {
        list.forEach(System.out::println);
    }

    private static Comparator<MyItem> getComparator() {
        for (Comparator<MyItem> comparator : serviceLoader) {
            System.out.println(comparator.getClass().getName());
            return comparator;
        }
        throw new RuntimeException("comparator is not found");
    }
}

參考文獻:

http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html

=========END=========

相關文章
相關標籤/搜索