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

发布时间:2021-06-26 14:29:41 作者:chen
来源:亿速云 阅读:494

这篇文章主要介绍“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";
    }
}

@Test
public void test1(){
    ExtensionLoader<AdaptiveExt> 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.DubboAdaptiveExt
cloud=com.alibaba.dubbo.demo.provider.adaptive.impl.SpringCloudAdaptiveExt
thrift=com.alibaba.dubbo.demo.provider.adaptive.impl.ThriftAdaptiveExt
com.alibaba.dubbo.demo.provider.adaptive.impl.AdaptiveExtWrapper
运行代码,输出:
before
thrift
after

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<Class<?>> 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<String, Class<?>> extensionClasses, 
              java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
    // 删去无关代码
    // 判断是否是Wrapper类型
    else if (isWrapperClass(clazz)) {
        Set<Class<?>> wrappers = cachedWrapperClasses;
        if (wrappers == null) {
            cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
            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的效果. Dubbo的SPI机制介绍以及Dubbo通过Wrapper实现AOP的方法

刚刚分析的只有一个Wrapper类的情况,现在分析有两个的情况,它的Debug结果如下图,清晰易懂 Dubbo的SPI机制介绍以及Dubbo通过Wrapper实现AOP的方法

输出结果是:
before
before2
thrift
after2
after
更新后的配置文件:
dubbo=com.alibaba.dubbo.demo.provider.adaptive.impl.DubboAdaptiveExt
cloud=com.alibaba.dubbo.demo.provider.adaptive.impl.SpringCloudAdaptiveExt
thrift=com.alibaba.dubbo.demo.provider.adaptive.impl.ThriftAdaptiveExt
com.alibaba.dubbo.demo.provider.adaptive.impl.AdaptiveExtWrapper
com.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的方法”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

推荐阅读:
  1. dubbo的SPI应用与原理是什么
  2. 什么是Dubbo SPI机制

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

spi dubbo

上一篇:HDFS中怎么实现本地文件上传

下一篇:如何解决bootstrap-select动态加载数据不显示的问题

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》