欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

Dubbo学习记录----JDK之SPI机制

时间:2023-05-14
JDK之SPI机制

个人理解

SPI就是一种约定机制,通常情况下, 我们服务都会有一个接口和一个实现类,当服务提供者提供某个服务时,需要在/meta-INF/services/目录下创建以接口路径命名的文在这个文件中, 指定我们实现的服务com.demo.impl.UserServiceImpl;

package com.tuling;public interface Product { void use();}public class Phone implements Product{ @Override public void use() { System.out.println("call"); }}package com.tuling;public class Food implements Product{ @Override public void use() { System.out.println("eat"); }}

在/meta-INF/services/创建一个com.demo.UserService文件

com.tuling.Phonecom.tuling.Food

JDK 的SPI调用机制

ServiceLoader productServiceLoader = ServiceLoader.load(Product.class); Iterator iterator = productServiceLoader.iterator(); while (iterator.hasNext()){ Product product = iterator.next(); product.use();}运行结果:calleat

ServiceLoader是JDK自带实现的SPI扫描类, 传入接口类Class信息, 然后JDK会根据接口的路径信息去扫描/meta-INF/services/com.tuling.Product文件然后将文件里面的内容一行一行全部读取出来,使用反射技术,将指定的实现类Phone,Food通过反射实例化, 放入某种数据结构容器中;

通过上面的简单例子, 差不多就可以理解SPI是个什么东西。

SPI机制的作用

步入正题, 那么JDK提供SPI机制的作用是什么呢?

解耦与实现组件化,模块化;可以提供一套接口规范, 每个依赖包提供接口实现类,然后在/WEB-INF/services下的以接口路径命令的文件里, 指定包的实现类,项目启动的时候, 就会去扫描/WEB-INF/services下的文件,一起使用; SPI机制常见举例

举个例子: 我们开发使用的DB操作, 一般会有Mysql, Oracle等,那么JDBC中, 有一个DriverManger类, 用来获取数据库连接;
JDBC提供了一个java.sql.Driver 接口,当我们使用不同的数据库时,各大厂商(如Mysql、Oracle)会根据一个统一的规范(java.sql.Driver)开发各自的驱动实现逻辑,客户端使用jdbc时不需要去改变代码,mysql依赖包中 /WEB-INF/services/有一个java.sql.Driver文件, 内容指定了Driver的实现类是com.mysql.jdbc.Driver, oracle依赖包中/WEB-INF/services/也有一个java.sql.Driver,内容指定了Driver的实现类是oracle.jdbc.driver.OracleDriver;

package java.sql;import java.util.Iterator;import java.util.ServiceLoader;import java.security.AccessController;import java.security.PrivilegedAction;import java.util.concurrent.CopyOnWriteArrayList;import sun.reflect.CallerSensitive;import sun.reflect.Reflection;public class DriverManager { @CallerSensitive public static Connection getConnection(String url, java.util.Properties info) throws SQLException { return (getConnection(url, info, Reflection.getCallerClass())); } //...} // Worker method called by the public getConnection() methods. private static Connection getConnection( String url, java.util.Properties info, Class<?> caller) throws SQLException { ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; synchronized(DriverManager.class) { // synchronize loading of the correct classloader. if (callerCL == null) { callerCL = Thread.currentThread().getContextClassLoader(); } } if(url == null) { throw new SQLException("The url cannot be null", "08001"); } for(DriverInfo aDriver : registeredDrivers) { // If the caller does not have permission to load the driver then // skip it. if(isDriverAllowed(aDriver.driver, callerCL)) { try { println(" trying " + aDriver.driver.getClass().getName()); Connection con = aDriver.driver.connect(url, info); if (con != null) { // Success! return (con); } } catch (SQLException ex) { if (reason == null) { reason = ex; } } } else { println(" skipping: " + aDriver.getClass().getName()); } } }

for(DriverInfo aDriver : registeredDrivers) 循环中的registeredDrivers代表的就是所有的Driver实现类,再根据每个驱动Driver实现类去连接具体的数据库;
而我们项目中可以一次引入mysql,oracle等多种数据库, 只需要在Mybatis的配置文件中指定使用哪种数据库, 进而再获取连接的时候,创建相关数据库的连接;

Java SPI机制的特点

优点:

插件化模块化

缺点:

不够灵活;
只可以获取所有的 规范实现, 做不到只获取部分规范实现;
项目可能使用10种数据库,就需要导入10种数据库包,我们短时间内只用到了3种 他就会将10种数据库的规范实现Driver全部扫描进来, 而不能只获取3种; 总结

Dubbo的SPI扩展机制就是对Java SPI机制的扩展, 使其更加灵活可用;

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。