为接口提供可插拔架构并不难。普通的 JRE 提供了必要的功能,而不需要额外的框架。因此,如果您有一个接口serviceexample.RandomNumberGenerator
,则可插入 RNG 的代码可能如下所示:
package serviceexample;
import java.util.Iterator;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
public final class RngService
{
private RngService(){}
private static final ServiceLoader<RandomNumberGenerator> LOADER
= ServiceLoader.load(RandomNumberGenerator.class);
public static RandomNumberGenerator getRandomNumberGenerator()
{
return LOADER.iterator().next();
}
public static Iterator<RandomNumberGenerator> getAllRandomNumberGenerators()
{
return LOADER.iterator();
}
public static RandomNumberGenerator getSpecificRandomNumberGenerator(String name)
{
try
{
return Class.forName(name).asSubclass(RandomNumberGenerator.class).newInstance();
} catch(InstantiationException | IllegalAccessException | ClassNotFoundException | ClassCastException ex)
{
throw new ServiceConfigurationError(name, ex);
}
}
}
这个类允许应用程序只请求一个实现,浏览所有可用的实现或请求一个特定的实现。后者可以由系统属性提供,例如-Drng=class
. 所以最简单的用法是RandomNumberGenerator r=RngService.getRandomNumberGenerator();
. 更高级的用途是:
String name=System.getProperty("rng");
RandomNumberGenerator r=name!=null?
RngService.getSpecificRandomNumberGenerator(name):
RngService.getRandomNumberGenerator();
现有实现类由META-INF/serviceexample.RandomNumberGenerator
包含特定实现的 jar 文件中的文件指定。另请参阅http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider