您当前的位置: 首页 >  dubbo

Dubbo SPI机制使用

发布时间:2022-07-10 15:31:05 ,浏览量:8

Java SPI机制博客传送门:https://blog.csdn.net/qq_42402854/article/details/125705159 注意:JDK SPI会一次性实例化扩展点的所有实现。

Dubbo没有使用JDK的SPI机制,而是自己实现的一套SPI机制。在Dubbo的源码中,很多地方会存在下面这样的三种代码:

//获取自适应扩展点
ExtensionLoader.getExtensionLoader(xxx.class).getAdaptiveExtension();
//获取指定名称的扩展点
ExtensionLoader.getExtensionLoader(xxx.class).getExtension(name);
//激活扩展点
ExtensionLoader.getExtensionLoader(xxx.class).getActivateExtension(url, key);

在Dubbo中,SPI贯穿整个Dubbo的核心,所以理解Dubbo中的SPI对于理解Dubbo的原理有着至关重要的作用。

  • 在Java中,通过 java.util.ServiceLoader 来发现动态加载具体的实现类到JVM中。
  • 在Spring中,SpringFactoriesLoader这个类,它也是一种SPI机制。
  • 在Dubbo中,ExtensionLoader这个类,它也是一种SPI机制。
一、Dubbo SPI机制使用 1、Dubbo的 SPI机制

Dubbo的 SPI机制:来自《Apache Dubbo与实战》一书中截图。 在这里插入图片描述 在这里插入图片描述

1.1 扩展点注解 1.1.1 @SPI注解

@SPI注解可以使用在类,接口和枚举上。

主要作用就是标记这个接口是一个 Dubbo SPI接口,即一个扩展点。 value,表示可以设置默认的实现类

@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface SPI { /**
     * default extension name
     */ String value() default ""; } 
1.1.2 @Adaptive注解

在这里插入图片描述 @Adaptive注解 可以标记在类、接口、枚举类和方法上。

自适应扩展点的知识,表示在运行时使用那个实现类。 当该注解使用在类上时,只能有一个实现类上可以加 @Adaptive注解,如果多个实现类都有该注解会抛出异常。

包装类等其他的自行了解。

@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface Adaptive { String[] value() default {}; } 
1.1.3 @Acticate注解

@Acticate注解 可以标记在类、接口、枚举类和方法上。

默认自动激活,主要使用在多个扩展点实现、还可以根据不同条件被激活的场景中。

@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface Activate { String[] group() default {}; String[] value() default {}; String[] before() default {}; String[] after() default {}; int order() default 0; } 
2、获取Protocol扩展点
public static void main(String[] args) { ExtensionLoader<Protocol> extensionLoader = ExtensionLoader.getExtensionLoader(Protocol.class); Protocol dubbo = extensionLoader.getExtension("dubbo"); System.out.println("dubbo 指定名称的扩展点:" + dubbo); System.out.println("dubbo 自适应扩展点:" + extensionLoader.getAdaptiveExtension()); System.out.println("dubbo 默认扩展点协议:" + extensionLoader.getDefaultExtension()); System.out.println("dubbo 获取所有扩展点协议:" + extensionLoader.getSupportedExtensions()); } 

在这里插入图片描述

Protocol接口源码如下: 在这里插入图片描述

二、自定义扩展点

这里写个 demo 感受一下 dubbo的SPI机制。

1、定义扩展点和实现类 1.1 扩展点

@SPI注解:value,表示设置默认的实现类

@SPI("MyLog") public interface MyLog { void debug(); } 
1.2 实现类

这里定义三个实现类。

@Activate public class MyLog4j implements MyLog{ @Override public void debug() { System.out.println("==========dubbo MyLog4j"); } } @Activate public class MyLogback implements MyLog{ @Override public void debug() { System.out.println("==========dubbo MyLogback"); } } @Adaptive //@Activate public class MyAdaptiveLog implements MyLog{ @Override public void debug() { System.out.println("==========dubbo MyAdaptiveLog"); } } 
2、创建配置文件

在项目resources目录下新建一个META-INF/dubbo/文件夹。

  • 在 META-INF/dubbo/目录下,创建一个文件,文件名为该SPI接口的全限定名。
  • 文件内容是key=具体实现类的全限定名,如果有多个,则用分行符分隔。

在这里插入图片描述

3、测试,加载实现类

在 代码中通过org.apache.dubbo.common.extension.ExtensionLoader来加载具体的实现类。

@Test public void test() { ExtensionLoader<MyLog> extensionLoader = ExtensionLoader.getExtensionLoader(MyLog.class); MyLog myLogback = extensionLoader.getExtension("myLogback"); System.out.println("MyLog 指定名称的扩展点:" + myLogback); myLogback.debug(); // 获取实现了@Adaptive注解的实现类 System.out.println("MyLog 自适应扩展点:" + extensionLoader.getAdaptiveExtension()); System.out.println("MyLog 默认扩展点协议:" + extensionLoader.getDefaultExtension()); System.out.println("MyLog 获取所有扩展点:" + extensionLoader.getSupportedExtensions()); } 

在这里插入图片描述

– 求知若饥,虚心若愚。

关注
打赏
1688896170
查看更多评论

暂无认证

  • 8浏览

    0关注

    105695博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.0840s