首页 > 其他分享 >SPI机制在ShardingSphere中的应用

SPI机制在ShardingSphere中的应用

时间:2022-10-14 21:02:26浏览次数:53  
标签:service SQLParserEntry sql each SPI 实例 ShardingSphere 机制

SPI机制在ShardingSphere中的应用

之前我们讲过一篇SPI机制在Skywalking中的应用,这篇我们说一说ShardingSphere又是如何使用SPI机制的

Sql解析器

Sql解析器的功能就是用来解析SQL的,它的实例创建是通过对应的工厂类SQLParserFactory来产生的的。

获取实例

我们看一下SQLParserFactory这个工厂类的获取实例的方法:

public static SQLParser newInstance(final String databaseTypeName, final String sql) {
    for (SQLParserEntry each : NewInstanceServiceLoader.newServiceInstances(SQLParserEntry.class)) {
        if (each.getDatabaseTypeName().equals(databaseTypeName)) {
            return createSQLParser(sql, each);
        }
    }
    throw new UnsupportedOperationException(String.format("Cannot support database type '%s'", databaseTypeName));
}

这里用到了NewInstanceServiceLoader来获取SQLParserEntry的对象信息,这和Java的SPI机制,我们深入看一下这个类的newServiceInstances()方法:

public static <T> Collection<T> newServiceInstances(final Class<T> service) {
    Collection<T> result = new LinkedList<>();
    if (null == SERVICE_MAP.get(service)) {
        return result;
    }
    for (Class<?> each : SERVICE_MAP.get(service)) {
        result.add((T) each.newInstance());
    }
    return result;
}

这个是直接从缓存中来获取的,那么缓存的数据又从哪里来的呢?

注册实例

我们从NewInstanceServiceLoader的register()方法可以看出:

public static <T> void register(final Class<T> service) {
        for (T each : ServiceLoader.load(service)) {
            registerServiceClass(service, each);
        }
}
private static <T> void registerServiceClass(final Class<T> service, final T instance) {
  ....
  SERVICE_MAP.put(service, serviceClasses);
}

从这段代码中我们就可以看出来,底层还是使用的Java的SPI机制来加载SQLParserEntry接口的实现类的实例,将 SPI 服务注册到新实例的映射中。因为SQLParserEntry接口所在的包是 org.apache.shardingsphere.sql.parser.spi.SQLParserEntry,所以它的实现类的配置所在的配置文件与这个类权限定名一致。不同的数据库对应的不同的解析SQL的SQLParserEntry实现类不同,mysql中的实现类是MySQLParserEntry,我们在shardingsphere-sql-parser-mysql模块的resoures文件夹的META-INF/services 目录下面可以看到存在org.apache.shardingsphere.sql.parser.spi.SQLParserEntry文件定义了SQLParserEntry的实现类为org.apache.shardingsphere.sql.parser.MySQLParserEntry,而shardingsphere-sql-parser-oracle模块中定义的是org.apache.shardingsphere.sql.parser.OracleParserEntry

配置中心

ShardingSphere的配置中心支持Apollo和Zookeeper,配置中心的灵活切换也使用到了Java的SPI机制

ConfigCenterServiceLoader是通过SPI机制来进行加载配置中心ConfigCenter的实现类

注册实例

ConfigCenterServiceLoader的静态方法中直接调用了上面我们分析的NewInstanceServiceLoader类的register()方法加载配置 的ConfigCenter的实例,sharding-orchestration-config-zookeeper-curator模块定义的实现类是CuratorZookeeperConfigCenter,sharding-orchestration-config-apollo模块定义的实现类是ApolloConfigCenter

获取实例

ConfigCenterServiceLoader的load()方法是从SPI机制中来加载配置中心实例,调用了它的父类TypeBasedSPIServiceLoader的newService()方法,而这个方法中又是调用NewInstanceServiceLoader的newServiceInstances(classType)方法来获取实例,其中classType是配置中心的类型,这个值在ConfigCenter的不同实现类中值不同。

总结

这篇文章我们讲了ShardingSphere是如何使用Java的SPI机制,列出来SQL解析器和配置中心的两个例子

在使用Java的SPI机制的要注意以下几点:

  1. 不同的功能对应有相同接口的不同实现类可以使用SPI机制
  2. SPI机制中配置文件在resoures文件夹的META-INF/services 目录下,文件名为接口名,文件内容为需要加载的接口的具体实现类的全限定名

❤️ 感谢大家

如果你觉得这篇内容对你挺有有帮助的话:

  1. 欢迎关注我❤️,点赞

    标签:service,SQLParserEntry,sql,each,SPI,实例,ShardingSphere,机制
    From: https://blog.51cto.com/u_15460453/5757959

相关文章