很多框架中,为了实现更好的扩展机制,都是用了JDK支持的SPI机制,本文简单介绍了一下,并提供了快速实现的示例
Java SPI(Service Provider Interface)是一种JDK支持的扩展机制,可以为某个接口寻找服务实现的机制,有点类似于IOC的思想,将装配的控制权移到了程序之外。
Java SPI
MySQL Driver
javax.servlet.ServletContainerInitializer
类似于JDK中的java.sql.Driver
public interface Scorer {
double score(String first, String second);
}
public class ScorerManager {
private static final Map<String, Scorer> SCORER_MAP = new HashMap<>(16);
static {
loadInitialScorers();
System.out.println("Scorer Manager initialized");
}
public static void registerScore(Scorer scorer) {
SCORER_MAP.putIfAbsent(scorer.getClass().getName(), scorer);
}
public static Scorer getScore(String scoreName) {
Scorer scorer = SCORER_MAP.get(scoreName);
if (scorer == null) {
throw new RuntimeException("cannot not find score with name:" + scoreName);
}
return scorer;
}
private static void loadInitialScorers() {
ServiceLoader<Scorer> serviceLoader = ServiceLoader.load(Scorer.class);
for (Scorer scorer : serviceLoader) {
//这里可以什么都不做,只是出发实现类的构造函数和静态模块
//其实也可以在这里完成注册,这样的话各个实现类会更加简单。不过在实现类中实现注册,会更加灵活,因为实现类在注册之前也许还需要做一些初始化的工作
}
}
}
类似于mysql中的com.mysq.Driver
和com.mysql.cj.jdbc.Drive
r, h2中的org.h2.Driver
public class BarScorer implements Scorer {
static {
ScorerManager.registerScore(new BarScorer());
System.out.println("BarScorer initialized");
}
@Override
public double score(String first, String second) {
return 0;
}
}
META-INF/services/com.tenmao.Scorer
文件com.tenmao.BarScorer
public static void main(String[] args) {
Scorer score = ScorerManager.getScore("com.tenmao.BarScorer");
double scoreOne = score.score("1", "1");
System.out.println(scoreOne);
}