SPI机制在ShardingSphere中的应用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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. 欢迎关注我❤️,点赞

    以上是关于SPI机制在ShardingSphere中的应用的主要内容,如果未能解决你的问题,请参考以下文章

    某厂面试:如何优雅使用 SPI 机制

    Java SPI 机制在 Flink 中的应用(源码分析)

    SPI机制之Dubbo中的SPI

    ShardingSphere4.1.1:Sharding-JDBC数据加密及SPI加密策略实现

    Dubbo中的SPI机制实现,自定义对接SPI

    java中的SPI机制