dubbo原理之dubbo SPI

本节目的:Dubbo SPI是dubbo所有扩展机制的核心,所以非常之重要!!所以为了让大家全面的了解dubbo SPI机制,见见结合dubbo源码以及官网,整理了dubbo spi机制。以及对比Java原生的spi,dubbo spi的其他特性。本章所有案例代码已经上传https://github.com/lengweijian/dubbo.git . lazy的小伙伴儿可以自行下载调试。

1、SPI简介

    SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。Dubbo良好的扩展性与两个方面是离不开的,一是框架针对不同的应用场景,恰到好处地使用各种设计模式。二就是本章介绍的加载机制,基于Dubbo SPI机制实现了dubbo的整个框架的接口和接口的实现类的良好解偶,奠定了扩展性的基础。

2、Java SPI

在介绍dubbo spi之前,先介绍Java spi。

  • 在 META-INF/services/ 目录中创建以接口全限定名命名的文件,该文件内容为API具体实现类的全限定名
  • 使用 ServiceLoader 类动态加载 META-INF 中的实现类
  • 如 SPI 的实现类为 Jar 则需要放在主程序 ClassPath 中
  • API 具体实现类必须有一个不带参数的构造方法

第一步,创建一个服务的接口,用于向外提供服务。


public interface DemoService {
    void sayHi(String msg);
}

第二步,再创建服务接口的第一个实现。


public class DemoServiceImpl_01 implements DemoService {
    @Override
    public void sayHi(String msg) {
        System.out.println("hello !!" + msg + "DemoServiceImpl_01....");
        return ;
    }
}

第三步,再创建服务接口的第二个实现。


public class DemoServiceImpl_02 implements DemoService {
    @Override
    public void sayHi(String msg) {
        System.out.println("hello !!" + msg + "DemoServiceImpl_02....");
        return ;
    }
}

第四步,在classpath下创建名称为文件夹【/META-INF/services】,这里名称、包文件层级固定,创建一个文件,名称为刚才服务接口的全路径,因为我这里的全路径为【com.atlwj.aop.service.DemoService】,所以你要改成你本地的接口全路径。文件的内容如下:


com.atlwj.aop.service.impl.DemoServiceImpl_01
com.atlwj.aop.service.impl.DemoServiceImpl_02

说明:文件内容为服务提供接口的实现类的全路径,路径和路径之间要换行。

第五步,创建测试类:


public class SPI_APP {
    public static void main(String[] args) {
        // 这句话的意思就是加载DemoService接口的实现类
        ServiceLoader<DemoService> serviceLoader =  ServiceLoader.load(DemoService.class);
		// 通过迭代器遍历每个服务实现
        Iterator<DemoService> iterator = serviceLoader.iterator();
        while (iterator.hasNext() && serviceLoader != null){
            DemoService helloService = iterator.next();
            helloService.sayHi("lengweijian");
        }
    }
}

运行结果:

运行结果
应用场景:JDBC

2.Dubbo SPI(重点)

简介:跟Java SPI相比,dubbo spi做了一定的优化和改进。主要包括:

  • jdk标准的SPI会一次性的实例化所有扩展点的实现类,如果其中有的实现类初始化很耗时,那么如果这个类不用的话,它也会加载,就会出现资源的浪费。
  • 如果扩展加载失败,则连扩展的名称也获取不到了。
  • dubbo spi增加了IOC(dubo仅仅支持setter方法的注入)和AOP的支持。下边会介绍。

2.1 dubbo spi 使用

第一步,创建服务提供接口,注意这里的@SPI注解不能少!!!


import org.apache.dubbo.common.extension.SPI;

@SPI
public interface DemoService {
    void sayHi(String msg);
}

第二步,创建两个实现类


import com.atlwj.aop.service.DemoService;

public class DemoServiceImpl_01 implements DemoService {
    @Override
    public void sayHi(String msg) {
        System.out.println("hello !!" + msg + "DemoServiceImpl_01.....");
        return ;
    }
}
import com.atlwj.aop.service.DemoService;

public class DemoServiceImpl_02 implements DemoService {
    @Override
    public void sayHi(String msg) {
        System.out.println("hello !!" + msg + "DemoServiceImpl_02.....");
        return ;
    }
}

第三步,在classpath下创建文件夹【/META-INF/dubbo】名称位置固定,创建名称为服务提供接口的全路径的文件,因为见见的是【com.atlwj.aop.service.DemoService】在这里插入图片描述

第四步,将服务提供接口实现类的全路径写在刚才第三步的文件里,但是跟Java spi不同的是可以给每个实现类添加key值,用【=】分开,如:在这里插入图片描述

第五步,创建测试类


import com.atlwj.aop.service.DemoService;
import org.apache.dubbo.common.extension.ExtensionLoader;

/**
 * dubbo spi特性:
 *      1.自动注入: setter
 *      2.AOP: Wrapper01、Wrapper02
 */
public class Dubbo_SPI_APP {
    public static void main(String[] args) {
		// <1> 获取扩展加载器
        ExtensionLoader<DemoService> extensionLoader = ExtensionLoader.getExtensionLoader(DemoService.class);
		// <2> 根据指定的key值获取你想要的服务实现类实例
        DemoService extension = extensionLoader.getExtension("02");
		// <3> 调用服务方法
        extension.sayHi("lengweijian");
    }
}



启动测试类:

运行结果

2.2 dubbo spi 特性

  • 特性一:AOP
    第一步,创建增强类,实现服务提供接口。

public class DemoServiceWrapper implements DemoService {
	
    private DemoService demoService;
	
	// 在这里将服务提供接口使用构造器注入进来
    public DemoServiceWrapper(DemoService demoService){  //具体的实现类
        this.demoService = demoService;
    }

    @Override
    public void sayHi(String msg) {
        System.out.println("Wrapper" + "before.....");
        // before 方法前置增强 
        demoService.sayHi(msg);
        // after 方法后置增强
        System.out.println("Wrapper" + "after.....");

    }
}

第二步,在【com.atlwj.aop.service.DemoService】文件里边加上包装类的全路径

在这里插入图片描述
启动测试类:

测试结果
结果发现,包装类实现了对目标类的增强。

如果重复包装,重复以上操作。当前的文件下:
在这里插入图片描述
结果:
在这里插入图片描述
以上是dubbo spi aop的特性展示。

总结:dubbo spi与java spi不同的是,可以在服务提供接口文件内指定实现类的key值,然后在这里插入图片描述获取扩展类的时候,可以指定的获取,不用迭代或者判断。

并且可以对目标实现的目标方法进行没有代码侵入性的多重增强。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值