前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >框架必备的SPI扩展机制

框架必备的SPI扩展机制

作者头像
十毛
发布2019-05-15 14:08:31
8190
发布2019-05-15 14:08:31
举报

很多框架中,为了实现更好的扩展机制,都是用了JDK支持的SPI机制,本文简单介绍了一下,并提供了快速实现的示例

SPI

Java SPI(Service Provider Interface)是一种JDK支持的扩展机制,可以为某个接口寻找服务实现的机制,有点类似于IOC的思想,将装配的控制权移到了程序之外。

Java SPI

SPI常用场景

  • 数据库驱动加载

MySQL Driver

  • Servlet API中的javax.servlet.ServletContainerInitializer
  • Dubbo中的类SPI机制,实现功能点的扩展(Dubbo可扩展机制实战

接口定义方

类似于JDK中的java.sql.Driver

  • 接口
代码语言:javascript
复制
public interface Scorer {
    double score(String first, String second);
}
  • 管理器
代码语言:javascript
复制
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.Drivercom.mysql.cj.jdbc.Driver, h2中的org.h2.Driver

  • 实现类
代码语言:javascript
复制
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文件
代码语言:javascript
复制
com.tenmao.BarScorer

接口使用方

  • 用户应用程序
代码语言:javascript
复制
public static void main(String[] args) {
    Scorer score = ScorerManager.getScore("com.tenmao.BarScorer");
    double scoreOne = score.score("1", "1");
    System.out.println(scoreOne);
}

注意事项

  • 接口实现类必须包含无参构造函数(默认就有)
  • 一般在XxxManager中不会注册实现类,而是交由实现类中静态模块完成。这样会存在一个问题,一个实现类会生成至少两个对象,其中一个对象被ServiceLoader生成后会被垃圾回收。

参考

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.05.09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SPI
  • SPI常用场景
  • 接口定义方
  • 接口实现方
  • 接口使用方
  • 注意事项
  • 参考
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档