Dubbo学习记录(三)----JDK之SPI机制

JDK之SPI机制

个人理解

  1. SPI就是一种约定机制,通常情况下, 我们服务都会有一个接口和一个实现类,当服务提供者提供某个服务时,需要在/META-INF/services/目录下创建以接口路径命名的文
  2. 在这个文件中, 指定我们实现的服务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.Phone
com.tuling.Food

JDK 的SPI调用机制

 ServiceLoader<Product> productServiceLoader = ServiceLoader.load(Product.class);
 Iterator<Product> iterator = productServiceLoader.iterator();
 while (iterator.hasNext()){
      Product product = iterator.next();
      product.use();
}

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

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

SPI机制的作用

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

  1. 解耦
  2. 与实现组件化,模块化;
  3. 可以提供一套接口规范, 每个依赖包提供接口实现类,然后在/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机制的特点

优点:

  1. 插件化
  2. 模块化

缺点:

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

总结

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

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值