今天在看Hadoop源代的時候發現,在FileSystem中用到了java.util.ServiceLoader這個類來從配置文件中加載子類或者接口的實現類。以前從來沒有使用過這個類,進去大概看了一下具體的實現。主要是從META-INF/services這個目錄下的配置文件加載給定接口或者基類的實現,ServiceLoader會根據給定的類的full name來在META-INF/services下面找對應的文件,在這個文件中定義了所有這個類的子類或者接口的實現類,返回一個實例。
下面以一個具體的例子來說明一下ServiceLoader的具體使用,類似Hadoop FileSystem中的實現。
首先定義一個接口,具體如下:
public interface IService {
public String sayHello();
public String getScheme();
}
該接口有兩個子類,分別為HDFSService和LocalService:
public class HDFSService implements IService {
@Override
public String sayHello() {
return "Hello HDFS!!";
}
@Override
public String getScheme() {
return "hdfs";
}
}
public class LocalService implements IService {
@Override
public String sayHello() {
return "Hello Local!!";
}
@Override
public String getScheme() {
return "local";
}
}
需要在META-INF/services下以IService這個類的全名來新建立一個文件,文件中的內容為兩個實現類的全名,如下:
org.hadoop.java.HDFSService
org.hadoop.java.LocalService
所有的實現和配置都已經完成,下面寫一個測試類來看一下結果:
public class ServiceLoaderTest {
/**
* @param args
*/
public static void main(String[] args) {
//need to define related class full name in /META-INF/services/....
ServiceLoader<IService> serviceLoader = ServiceLoader
.load(IService.class);
for (IService service : serviceLoader) {
System.out.println(service.getScheme()+"="+service.sayHello());
}
}
}