5Dubbo的SPI机制分析4Dubbo通过Wrapper实现AOP

39次阅读

共计 3995 个字符,预计需要花费 10 分钟才能阅读完成。

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);
        }
        // 依赖注入,
        injectExtension(instance);
        
        // cachedWrapperClasses,
        Set<Class<?>> wrapperClasses = cachedWrapperClasses;
        if (wrapperClasses != null && !wrapperClasses.isEmpty()) {for (Class<?> wrapperClass : wrapperClasses) {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 {
    // clazz 必须是 type 类型的, 否则抛异常
    if (!type.isAssignableFrom(clazz)) {
        throw new IllegalStateException("Error when load extension class(interface:" +
                type + ", class line:" + clazz.getName() + "), class"
                + clazz.getName() + "is not subtype of interface.");
    }
    // 判断 clazz 是否为标注了 @Adaptive 注解, 后面分析
    if (clazz.isAnnotationPresent(Adaptive.class)) {if (cachedAdaptiveClass == null) {cachedAdaptiveClass = clazz;} else if (!cachedAdaptiveClass.equals(clazz)) {
            throw new IllegalStateException("More than 1 adaptive class found:"
                    + cachedAdaptiveClass.getClass().getName()
                    + "," + clazz.getClass().getName());
        }
    }
    // 判断是否是 Wrapper 类型, 后面分析
    else if (isWrapperClass(clazz)) {
        Set<Class<?>> wrappers = cachedWrapperClasses;
        if (wrappers == null) {cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
            wrappers = cachedWrapperClasses;
        }
        wrappers.add(clazz);
    }
    // 程序进入此分支, 表明 clazz 是一个普通的拓展类,Robot 就是一个普通的拓展类
    else {
        // 检测 clazz 是否有默认的构造方法, 如果没有, 则抛出异常
        clazz.getConstructor();
        if (name == null || name.length() == 0) {name = findAnnotationName(clazz);
            if (name.length() == 0) {throw new IllegalStateException("No such extension name for the class" + clazz.getName() + "in the config" + resourceURL);
            }
        }
        String[] names = NAME_SEPARATOR.split(name);
        if (names != null && names.length > 0) {Activate activate = clazz.getAnnotation(Activate.class);
            if (activate != null) {cachedActivates.put(names[0], activate);
            }
            for (String n : names) {if (!cachedNames.containsKey(clazz)) {cachedNames.put(clazz, n);
                }
                Class<?> c = extensionClasses.get(n);
                if (c == null) {
                    // 存储名称到 class 的映射关系, 这样就解析好了一行
                    extensionClasses.put(n, clazz);
                } else if (c != clazz) {throw new IllegalStateException("Duplicate extension" + type.getName() + "name" + n + "on" + c.getName() + "and" + clazz.getName());
                }
            }
        }
    }
}

正文完
 0