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机制的要注意以下几点:
- 不同的功能对应有相同接口的不同实现类可以使用SPI机制
- SPI机制中配置文件在resoures文件夹的META-INF/services 目录下,文件名为接口名,文件内容为需要加载的接口的具体实现类的全限定名
❤️ 感谢大家
如果你觉得这篇内容对你挺有有帮助的话:
- 欢迎关注我❤️,点赞
以上是关于SPI机制在ShardingSphere中的应用的主要内容,如果未能解决你的问题,请参考以下文章