精尽 Dubbo 源码分析 —— 过滤器(一)之 ClassLoaderFilter

1.概述

在 ProtocolFilterWrapper 中,在服务引用和暴露时,#buildInvokerChain(invoker, key, group) 方法中,基于 Dubbo SPI Active 机制,加载匹配对应的过滤器数组,创建带有过滤器链的 Invoker 对象。代码如下:

/**
 * 创建带 Filter 链的 Invoker 对象
 *
 * @param invoker Invoker 对象
 * @param key 获取 URL 参数名
 * @param group 分组
 * @param  泛型
 * @return Invoker 对象
 */
private static  Invoker buildInvokerChain(final Invoker invoker, String key, String group) {
    Invoker last = invoker;
    // 获得过滤器数组
    List filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
    // 倒序循环 Filter ,创建带 Filter 链的 Invoker 对象
    if (!filters.isEmpty()) {
        for (int i = filters.size() - 1; i >= 0; i--) {
            final Filter filter = filters.get(i);
            final Invoker next = last;
            last = new Invoker() {

                @Override
                public Class getInterface() {
                    return invoker.getInterface();
                }

                @Override
                public URL getUrl() {
                    return invoker.getUrl();
                }

                @Override
                public boolean isAvailable() {
                    return invoker.isAvailable();
                }

                @Override
                public Result invoke(Invocation invocation) throws RpcException {
                    return filter.invoke(next, invocation);
                }

                @Override
                public void destroy() {
                    invoker.destroy();
                }

                @Override
                public String toString() {
                    return invoker.toString();
                }
            };
        }
    }
    return last;
}

2.ClassLoaderFilter

实现 Filter 接口,类加载器切换过滤器实现类。代码如下:

@Activate(group = Constants.PROVIDER, order = -30000)
public class ClassLoaderFilter implements Filter {

    @Override
    public Result invoke(Invoker invoker, Invocation invocation) throws RpcException {
        // 获得原来的类加载器
        ClassLoader ocl = Thread.currentThread().getContextClassLoader();
        // 切换当前线程的类加载器为服务接口的类加载器
        Thread.currentThread().setContextClassLoader(invoker.getInterface().getClassLoader());
        // 服务调用
        try {
            return invoker.invoke(invocation);
        } finally {
            // 切换当前线程的类加载器为原来的类加载器
            Thread.currentThread().setContextClassLoader(ocl);
        }
    }

}

作用是在设计目的中,切换到加载了接口定义的类加载器,以便实现与相同的类加载器上下文一起工作。

你可能感兴趣的:(dubbo源码解析)