我是靠谱客的博主 可爱心锁,这篇文章主要介绍dubbo之SPI Wrapper分析,现在分享给大家,希望可以做个参考。

写在前面

本文需要dubbo SPI的简单基础知识,对dubbo SPI不了解的朋友可以参考dubbo之SPI分析 。
源码!!!。

在dubbo之SPI分析 文章中我们分析了SPI机制,其中有种SPI是一个Wrapper类的情况,本文一起来看下Wrapper的使用,Wapper在dubbo中的作用类似于spring 中AOP,实现扩展类调用拦截的功能,现在考虑这样的一个场景,对于某个扩展类的调用,我们想要做以下的几件事:

复制代码
1
2
3
1:统计调用时长。 2:记录调用日志。

想要满足这个需求,我们就可以通过Wrapper类来实现,分别对应4个类,如下:

复制代码
1
2
3
4
5
BusinessTopInterface:SPI接口类。 MyConcreteBusinessTopInterface:目标扩展类。 CalWasteTimeWapper:统计调用耗时的Wapper类。 RecordInvokeLogWapper:记录调用日志的Wapper类。

类之间的结构关系如下图最终调用

在这里插入图片描述

下面我们就开始吧!

1:实例

1.1:定义扩展类接口

复制代码
1
2
3
4
5
6
7
import com.alibaba.dubbo.common.extension.SPI; @SPI public interface BusinessTopInterface { void sayHi(); }

1.2:定义扩展类

复制代码
1
2
3
4
5
6
7
public class MyConcreteBusinessTopInterface implements BusinessTopInterface { @Override public void sayHi() { System.out.println("MyConcreteBusinessTopInterface.sayHi ***111***"); } }

1.3:定义计算耗时Wrapper

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class CalWasteTimeWapper implements BusinessTopInterface { private BusinessTopInterface businessTopInterface; // 注意这里必须有一个接收BusinessTopInterface为唯一参数的构造函数,这样才会被识别为Wrapper类 public CalWasteTimeWapper(BusinessTopInterface businessTopInterfaceIn) { this.businessTopInterface = businessTopInterfaceIn; } @Override public void sayHi() { System.out.println("*** cal waste time begin***"); long startTime = System.currentTimeMillis(); // 调用被包裹的类,这里是RecordInvokeLogWapper businessTopInterface.sayHi(); System.out.println("invoke waste time is: " + (System.currentTimeMillis() - startTime)); } }

1.4:记录调用日志Wrapper

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class RecordInvokeLogWapper implements BusinessTopInterface { private BusinessTopInterface businessTopInterface; public RecordInvokeLogWapper(BusinessTopInterface businessTopInterfaceIn) { this.businessTopInterface = businessTopInterfaceIn; } @Override public void sayHi() { System.out.println("record invoke log to database!"); // 调用被包装的类,这里是真正的扩展类MyConcreteBusinessTopInterface this.businessTopInterface.sayHi(); } }

1.5:配置文件

我这里是dongshi.daddy.wrapper.BusinessTopInterface

注意wrapper的顺序,越往下的越先被调用。

复制代码
1
2
3
4
myConcreteBusinessTopInterface=dongshi.daddy.wrapper.MyConcreteBusinessTopInterface recordInvokeLogWapper=dongshi.daddy.wrapper.RecordInvokeLogWapper calWasteTimeWapper=dongshi.daddy.wrapper.CalWasteTimeWapper

1.6:main

复制代码
1
2
3
4
5
6
7
8
9
10
public class WrapperMain { public static void main(String[] args) { BusinessTopInterface myConcreteBusinessTopInterface = ExtensionLoader .getExtensionLoader(BusinessTopInterface.class) .getExtension("myConcreteBusinessTopInterface"); myConcreteBusinessTopInterface.sayHi(); } }

运行:

复制代码
1
2
3
4
5
*** cal waste time begin*** record invoke log to database! MyConcreteBusinessTopInterface.sayHi ***111*** invoke waste time is: 2013

1.7:原理分析重要!!!

当我们执行方法getExtension("myConcreteBusinessTopInterface")时会执行到代码com.alibaba.dubbo.common.extension.ExtensionLoader.createExtension,源码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class FakeCls { private T createExtension(String name) { Class<?> clazz = getExtensionClasses().get(name); if (clazz == null) { throw findException(name); } try { T instance = (T) EXTENSION_INSTANCES.get(clazz); if (instance == null) { EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } injectExtension(instance); Set<Class<?>> wrapperClasses = cachedWrapperClasses; // 2022-01-23 14:45:21 if (wrapperClasses != null && !wrapperClasses.isEmpty()) { for (Class<?> wrapperClass : wrapperClasses) { instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } return instance; } catch (Throwable t) { throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type + ") could not be instantiated: " + t.getMessage(), t); } } }

执行到2022-01-23 14:45:21处时instance确实是MyConcreteBusinessTopInterface,但是会被wrapperClasses进行层层包裹,如下debug:

在这里插入图片描述

执行后最终return的instance如下:

在这里插入图片描述

写在后面

没什么写的,就吟诗一首吧!

复制代码
1
2
3
古人学问无遗力,少壮工夫老始成。 纸上得来终觉浅,绝知此事要躬行。

最后

以上就是可爱心锁最近收集整理的关于dubbo之SPI Wrapper分析的全部内容,更多相关dubbo之SPI内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部