千家信息网

Dubbo的SPI机制介绍以及Dubbo通过Wrapper实现AOP的方法

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,这篇文章主要介绍"Dubbo的SPI机制介绍以及Dubbo通过Wrapper实现AOP的方法",在日常操作中,相信很多人在Dubbo的SPI机制介绍以及Dubbo通过Wrapper实现AOP的方法问题
千家信息网最后更新 2025年01月23日Dubbo的SPI机制介绍以及Dubbo通过Wrapper实现AOP的方法

这篇文章主要介绍"Dubbo的SPI机制介绍以及Dubbo通过Wrapper实现AOP的方法",在日常操作中,相信很多人在Dubbo的SPI机制介绍以及Dubbo通过Wrapper实现AOP的方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Dubbo的SPI机制介绍以及Dubbo通过Wrapper实现AOP的方法"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

1、Dubbo的通过Wrapper实现AOP例子

阅读此篇文章之前,建议先学习该系列前面几篇文章,会有一个更好的理解.

参考: Dubbo的SPI机制分析2-Adaptive详解、Dubbo的SPI机制分析3-Dubbo的IOC依赖注入

// 在原有接口、实现类的基础上再加一个Wrapper实现类public class AdaptiveExtWrapper implements AdaptiveExt {    private AdaptiveExt adaptiveExt;    // 实现一个Wrapper类的关键就是提供一个带类似参数的构造函数,后面代码会分析    public AdaptiveExtWrapper(AdaptiveExt adaptiveExt) {        this.adaptiveExt = adaptiveExt;    }    @Override    public String echo(String msg, URL url) {        // do something,实现了AOP        System.out.println("before");        adaptiveExt.echo(msg, url);        System.out.println("after");        // do something        return "wrapper";    }}
public class DubboAdaptiveExt implements AdaptiveExt {    private AdaptiveExt adaptiveExt;    // 此处DubboAdaptiveExt依赖注入一个AdaptiveExt 类型的实例,此处测试用例注入的是ThriftAdaptiveExt    public void setAdaptiveExt(AdaptiveExt adaptiveExt) {        this.adaptiveExt = adaptiveExt;    }    @Override    public String echo(String msg, URL url) {        System.out.println(this.adaptiveExt.echo(msg, url));        return "dubbo";    }}@Testpublic void test1(){    ExtensionLoader loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class);    AdaptiveExt adaptiveExtension = loader.getExtension("dubbo");    URL url = URL.valueOf("test://localhost/test");    adaptiveExtension.echo("d", url);}

同时记得dubbo的配置文件中要新增一行,否则dubbo框架无法扫描到Wrapper

dubbo=com.alibaba.dubbo.demo.provider.adaptive.impl.DubboAdaptiveExtcloud=com.alibaba.dubbo.demo.provider.adaptive.impl.SpringCloudAdaptiveExtthrift=com.alibaba.dubbo.demo.provider.adaptive.impl.ThriftAdaptiveExtcom.alibaba.dubbo.demo.provider.adaptive.impl.AdaptiveExtWrapper
运行代码,输出:beforethriftafter

2、Dubbo的通过Wrapper实现AOP源码分析

可以发现,上述代码先后输出before、after,中间输出thrift,这其实可以说明adaptiveExtension = loader.getExtension("dubbo")返回的是AdaptiveExtWrapper类型的实例,有点像静态代理,下面分析源代码.

// 核心代码,删去一些不重要代码private T createExtension(String name) {    // 这里也是通过dubbo的SPI机制去扫描dubbo的默认目录下的文件,去加载实现了AdaptiveExt的实现类,这里会    // 加载4个,包括AdaptiveExtWrapper,它就是下面的wrapperClasses中仅有的元素,下面先分析这个加载过程    Class clazz = getExtensionClasses().get(name);       try {        T instance = (T) EXTENSION_INSTANCES.get(clazz);        if (instance == null) {            EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());            instance = (T) EXTENSION_INSTANCES.get(clazz);        }        // 依赖注入,这里注入的就是ThriftAdaptiveExt类型的实例对象        injectExtension(instance);                // 所以这里面cachedWrapperClasses包含了AdaptiveExtWrapper类        Set> wrapperClasses = cachedWrapperClasses;        if (wrapperClasses != null && !wrapperClasses.isEmpty()) {            for (Class wrapperClass : wrapperClasses) {                // 先分析仅有一个Wrapper类的情况,将原有的instance作为参数传入AdaptiveExtWrapper                // 生成一个AdaptiveExtWrapper类型的instance,并为该instance依赖注入,这里的instance                // 没有什么好注入的                instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));            }        }        return instance;    } }
private void loadClass(Map> extensionClasses,               java.net.URL resourceURL, Class clazz, String name) throws NoSuchMethodException {    // 删去无关代码    // 判断是否是Wrapper类型    else if (isWrapperClass(clazz)) {        Set> wrappers = cachedWrapperClasses;        if (wrappers == null) {            cachedWrapperClasses = new ConcurrentHashSet>();            wrappers = cachedWrapperClasses;        }        // 是的话,会用HashSet记录下它,这说明wrapper类可以配置多个,后面分析多个的情况        wrappers.add(clazz);    }}
 // 这里判断是Wrapper类的逻辑很简单,如果该clazz里面有type类型的构造参数,那么它就是,否则会抛出异常,返回false private boolean isWrapperClass(Class clazz) {    try {        clazz.getConstructor(type);        return true;    } catch (NoSuchMethodException e) {        return false;    }}

观看下图可以发现,最后生成的instanceAdaptiveExtWrapper类型的,它里面有一个DubboAdaptiveExt类型变量,adaptiveExt里面有一个ThriftAdaptiveExt类型的变量,所以最后调用adaptiveExtension.echo("d", url)时的adaptiveExtension是AdaptiveExtWrapper类型的,所以输出结果如上,有了AOP的效果.

刚刚分析的只有一个Wrapper类的情况,现在分析有两个的情况,它的Debug结果如下图,清晰易懂

输出结果是:beforebefore2thriftafter2after
更新后的配置文件:dubbo=com.alibaba.dubbo.demo.provider.adaptive.impl.DubboAdaptiveExtcloud=com.alibaba.dubbo.demo.provider.adaptive.impl.SpringCloudAdaptiveExtthrift=com.alibaba.dubbo.demo.provider.adaptive.impl.ThriftAdaptiveExtcom.alibaba.dubbo.demo.provider.adaptive.impl.AdaptiveExtWrappercom.alibaba.dubbo.demo.provider.adaptive.impl.AdaptiveExtWrapper2
public class AdaptiveExtWrapper2 implements AdaptiveExt {    private AdaptiveExt adaptiveExt;    public AdaptiveExtWrapper2(AdaptiveExt adaptiveExt) {        this.adaptiveExt = adaptiveExt;    }    @Override    public String echo(String msg, URL url) {        // do something,实现了AOP        System.out.println("before2");        adaptiveExt.echo(msg, url);        System.out.println("after2");        // do something        return "wrapper";    }}

到此,关于"Dubbo的SPI机制介绍以及Dubbo通过Wrapper实现AOP的方法"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

0