Dubbo源码学习17

本篇幅分析Dubbo创建代理对象流程,我们在刚开始分析服务引用章节,提到了最终Dubbo会根据invoker使用proxyFactory创建代理对象,本篇幅主要目的就是为了分析proxyFactory.getProxy(invoker);

ReferenceConfig.createProxy(Map<String,String> map)

@SuppressWarnings({"unchecked", "rawtypes", "deprecation"})
    private T createProxy(Map<String, String> map) {
        URL tmpUrl = new URL("temp", "localhost", 0, map);
        final boolean isJvmRefer;
        //本地jvm引用配置
        if (isInjvm() == null) {
            // url 配置被指定,则不做本地引用
            if (url != null && url.length() > 0) {
                isJvmRefer = false;
                // 根据 url 的协议、scope 以及 injvm 等参数检测是否需要本地引用
                // 比如如果用户显式配置了 scope=local,此时 isInjvmRefer 返回 true
            } else if (InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) {
                isJvmRefer = true;
            } else {
                isJvmRefer = false;
            }
        } else {
            //injvm配置
            isJvmRefer = isInjvm().booleanValue();
        }
        //本地jvm引用
        if (isJvmRefer) {
            //new一个本地引用url injvm协议的并将Map的参数添加到URL对象中
            URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
            //创建invoker实例
            invoker = refprotocol.refer(interfaceClass, url);
            if (logger.isInfoEnabled()) {
                logger.info("Using injvm service " + interfaceClass.getName());
            }
        } else {
            //url不为空,指定的URL可能是对点对直连地址,也可能是注册中心URL
            if (url != null && url.length() > 0) {
                //按照;切分url字符串(因为url可能配置多个!!!)
                String[] us = Constants.SEMICOLON_SPLIT_PATTERN.split(url);
                if (us != null && us.length > 0) {
                    for (String u : us) {
                        //将字符串转换为URL对象
                        URL url = URL.valueOf(u);
                        //设置接口全限定名称的url
                        if (url.getPath() == null || url.getPath().length() == 0) {
                            url = url.setPath(interfaceName);
                        }
                        //检测 url 协议是否为 registry,若是,表明用户想使用指定的注册中心
                        if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                            //将map变成?key=value&key2=value2这种的,然后作为refer属性的值添加到url中
                            urls.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
                        } else {
                            //合并 url,移除服务提供者的一些配置(这些配置来源于用户配置的url属性)
                            //比如线程池相关配置。并保留服务提供者的部分配置,比如版本,group,时间戳等
                            //后将合并后的配置设置为 url 查询字符串中。
                            urls.add(ClusterUtils.mergeUrl(url, map));
                        }
                    }
                }
            } else {
                //加载注册中心url
                //registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=echo-consumer&dubbo=2.0.2&
                // pid=16304&registry=zookeeper&timestamp=1573441590938
                List<URL> us = loadRegistries(false);
                if (us != null && !us.isEmpty()) {
                    for (URL u : us) {
                        //加载监控中心配置,赞不关心
                        URL monitorUrl = loadMonitor(u);
                        if (monitorUrl != null) {
                            map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
                        }
                        //添加refer参数到url中
                        urls.add(u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
                    }
                }
                if (urls.isEmpty()) {
                    throw new IllegalStateException("No such any registry to reference " + interfaceName + " on the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please config <dubbo:registry address=\"...\" /> to your spring config.");
                }
            }
            //单个注册中心或服务提供者(服务直连,下同)
            if (urls.size() == 1) {
                //调用RegistryProtocol的refer方法创建invoker
                invoker = refprotocol.refer(interfaceClass, urls.get(0));
            //多个注册中心或多个服务提供者,或者两中情况都存在
            } else {
                List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
                URL registryURL = null;
                //获取所有Invoker
                for (URL url : urls) {
                    invokers.add(refprotocol.refer(interfaceClass, url));
                    if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                        registryURL = url; // use last registry url
                    }
                }
                //如果注册中心的url是没问题的;使用AvaliableCluster
                if (registryURL != null) { // registry url is available
                    // use AvailableCluster only when register's cluster is available
                    URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
                    invoker = cluster.join(new StaticDirectory(u, invokers));
                } else { // not a registry url
                    invoker = cluster.join(new StaticDirectory(invokers));
                }
            }
        }

        Boolean c = check;
        if (c == null && consumer != null) {
            c = consumer.isCheck();
        }
        if (c == null) {
            c = true; // default true
        }
        //如果要检查提供者是否存在但是invoker不可用,抛出异常
        if (c && !invoker.isAvailable()) {
            // make it possible for consumer to retry later if provider is temporarily unavailable
            initialized = false;
            throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());
        }
        if (logger.isInfoEnabled()) {
            logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl());
        }
        // create service proxy
        // 生成代理类
        return (T) proxyFactory.getProxy(invoker);
    }

代码最后一行,会通过ReferenceConfig的成员变量proxyFactory根据得到的Cluster Invoker对象创建代理对象,关于proxyFactory初始化

    private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();

根据dubbo的spi机制可知proxyFactory的类型为ProxyFactory$Adaptive

public class ProxyFactory$Adaptive implements com.alibaba.dubbo.rpc.ProxyFactory {
    public com.alibaba.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, com.alibaba.dubbo.common.URL arg2) throws com.alibaba.dubbo.rpc.RpcException {
        if (arg2 == null) throw new IllegalArgumentException("url == null");
        com.alibaba.dubbo.common.URL url = arg2;
        String extName = url.getParameter("proxy", "javassist");
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
        com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
        return extension.getInvoker(arg0, arg1, arg2);
    }

    public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0, boolean arg1) throws com.alibaba.dubbo.rpc.RpcException {
        if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
        com.alibaba.dubbo.common.URL url = arg0.getUrl();
        String extName = url.getParameter("proxy", "javassist");
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
        com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
        return extension.getProxy(arg0, arg1);
    }

    public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {
        if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
        com.alibaba.dubbo.common.URL url = arg0.getUrl();
        String extName = url.getParameter("proxy", "javassist");
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
        com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
        return extension.getProxy(arg0);
    }
}

由于ProxyFactory有包装类StubProxyFactoryWrapper所以最终获取得到的ProxyFactory的实例是StubProxyFactoryWrapper,它包装了JavassistProxyFactory对象。有图为证

ProxyFactory

  • ProxyFactory:创建代理和invoker抽象接口
@SPI("javassist")
public interface ProxyFactory {

    /**
     * 创建代理
     *
     * @param invoker
     * @return proxy
     */
    @Adaptive({Constants.PROXY_KEY})
    <T> T getProxy(Invoker<T> invoker) throws RpcException;

    /**
     * 创建代理
     *
     * @param invoker
     * @return proxy
     */
    @Adaptive({Constants.PROXY_KEY})
    <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException;

    /**
     * 创建Invoker
     *
     * @param <T>
     * @param proxy
     * @param type
     * @param url
     * @return invoker
     */
    @Adaptive({Constants.PROXY_KEY})
    <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;

}
  • AbstractProxyFactory:抽象的ProxyFactory的实现,帮我们实现了获取代理对象之前的准备工作,即创建代理对象需要的接口数组处理
  • JavassistProxyFactory:基于Javassist技术创建代理对象的ProxyFactory的实现
  • JdkProxyFactory:基于jdk动态代理创建代理对象的ProxyFactory的实现
  • StubProxyFactoryWrapper:实现了ProxyFactory接口,内部持有一个JdkProxyFactory或者JavassistProxyFactory对象,主要是代理对象的本地存根实现,关于本地存根参考http://dubbo.apache.org/zh-cn/docs/user/demos/local-stub.html,

StubProxyFactoryWrapper.getProxy(Invoker<T> invoker)

@Override
    @SuppressWarnings({"unchecked", "rawtypes"})
    public <T> T getProxy(Invoker<T> invoker) throws RpcException {
        //委托JavassistProxyFactory或者JdkProxyFactory创建代理对象
        T proxy = proxyFactory.getProxy(invoker);
        //
        if (GenericService.class != invoker.getInterface()) {
            String stub = invoker.getUrl().getParameter(Constants.STUB_KEY, invoker.getUrl().getParameter(Constants.LOCAL_KEY));
            if (ConfigUtils.isNotEmpty(stub)) {
                //获取接口类型
                Class<?> serviceType = invoker.getInterface();
                //本地存根配置判断
                if (ConfigUtils.isDefault(stub)) {
                    if (invoker.getUrl().hasParameter(Constants.STUB_KEY)) {
                        stub = serviceType.getName() + "Stub";
                    } else {
                        stub = serviceType.getName() + "Local";
                    }
                }
                try {
                    //加载本地存根类
                    Class<?> stubClass = ReflectUtils.forName(stub);
                    //判断本地存根类是否实现了serviceType,没有抛出异常
                    if (!serviceType.isAssignableFrom(stubClass)) {
                        throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + serviceType.getName());
                    }
                    try {
                        //查找本地存根类是否有 serviceType的构造函数
                        Constructor<?> constructor = ReflectUtils.findConstructor(stubClass, serviceType);
                        //有的话使用proxy对象创建stub对象返回
                        proxy = (T) constructor.newInstance(new Object[]{proxy});
                        //如果dubbo.stub.event 配置为true,export
                        URL url = invoker.getUrl();
                        if (url.getParameter(Constants.STUB_EVENT_KEY, Constants.DEFAULT_STUB_EVENT)) {
                            url = url.addParameter(Constants.STUB_EVENT_METHODS_KEY, StringUtils.join(Wrapper.getWrapper(proxy.getClass()).getDeclaredMethodNames(), ","));
                            url = url.addParameter(Constants.IS_SERVER_KEY, Boolean.FALSE.toString());
                            try {
                                export(proxy, (Class) invoker.getInterface(), url);
                            } catch (Exception e) {
                                LOGGER.error("export a stub service error.", e);
                            }
                        }
                    } catch (NoSuchMethodException e) {
                        throw new IllegalStateException("No such constructor \"public " + stubClass.getSimpleName() + "(" + serviceType.getName() + ")\" in stub implementation class " + stubClass.getName(), e);
                    }
                } catch (Throwable t) {
                    LOGGER.error("Failed to create stub implementation class " + stub + " in consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", cause: " + t.getMessage(), t);
                    // ignore
                }
            }
        }
        return proxy;
    }

上述代码的逻辑首先会,委托javassistProxyFactory或者jdkProxyFactory创建代理对象,然后判断此次调用invoker的url中的本地存根配置,如果需要创建本地存根,首先将调用的serviceType拼接Local或者Stub(比如最终拼接为HelloServiceStub)这种,然后加载本地存根类,然后判断本地存根类的构造函数是否合理,即本地存根类的构造函数必须以ServiceType构造,然后根据创建的代理对象proxy创建本地存根类的对象,最后判断是否需要export,需要export,就进行一次export好了。关于怎么使用本地存根不是本文重点内容,如有兴趣可以参考https://github.com/SpringStudent/dubbo/tree/master/study-dubbo/src/main/java/com/alibaba/dubbo/study/day04下的代码。

AbstractProxyFactory.getProxy(Invoker<T> invoker, boolean generic)

@Override
    public <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException {
        //接口数组
        Class<?>[] interfaces = null;
        //获取接口列表
        String config = invoker.getUrl().getParameter("interfaces");
        if (config != null && config.length() > 0) {
            //使用,切分接口列表
            String[] types = Constants.COMMA_SPLIT_PATTERN.split(config);
            if (types != null && types.length > 0) {
                //设置服务接口类和 EchoService.class 到 interfaces 中
                interfaces = new Class<?>[types.length + 2];
                interfaces[0] = invoker.getInterface();
                interfaces[1] = EchoService.class;
                //加载接口类放到interfaces[]数组中
                for (int i = 0; i < types.length; i++) {
                    interfaces[i + 1] = ReflectUtils.forName(types[i]);
                }
            }
        }
        //如果接口为null,放入下面这两个接口
        if (interfaces == null) {
            interfaces = new Class<?>[]{invoker.getInterface(), EchoService.class};
        }
        //为http和hessian调用添加支持 添加了GenericService
        if (!invoker.getInterface().equals(GenericService.class) && generic) {
            int len = interfaces.length;
            Class<?>[] temp = interfaces;
            interfaces = new Class<?>[len + 1];
            System.arraycopy(temp, 0, interfaces, 0, len);
            interfaces[len] = GenericService.class;
        }
        return getProxy(invoker, interfaces);
    }

上面大段代码都是用来获取 interfaces 数组的,我们继续往下看getProxy(invoker,interfaces)的代码实现。

JdkProxyFactory.getProxy(Invoker<T> invoker, Class<?>[] interfaces)

public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker));
    }

jdk动态代理创建代理对象,固定模板,我们重点分析javassistProxyFactory的实现

JavassistProxyFactory.getProxy(Invoker<T> invoker, Class<?>[] interfaces)

public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }

通过Proxy.getProxy方法获取Proxy对象,然后调用Proxy对象的newInstance方法创建代理对象

Proxy.getProxy(Class<?>... ics)

 public static Proxy getProxy(Class<?>... ics) {
        return getProxy(ClassHelper.getClassLoader(Proxy.class), ics);
    }

Proxy.getProxy(ClassLoader cl, Class<?>... ics)

/**
     * 获取proxy对象
     *
     * @param cl  class loader.
     * @param ics interface class array.
     * @return Proxy instance.
     */
    public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
        //如果接口数量超过了65535抛出异常,说吧你是不是学的jdk的可重入锁的源码!
        if (ics.length > 65535)
            throw new IllegalArgumentException("interface limit exceeded");
        StringBuilder sb = new StringBuilder();
        //遍历接口列表
        for (int i = 0; i < ics.length; i++) {
            String itf = ics[i].getName();
            //竟然不是接口抛出异常
            if (!ics[i].isInterface())
                throw new RuntimeException(itf + " is not a interface.");
            //加载接口类
            Class<?> tmp = null;
            try {
                tmp = Class.forName(itf, false, cl);
            } catch (ClassNotFoundException e) {
            }
            //不是同一个类加载器加载的clss抛出异常
            if (tmp != ics[i])
                throw new IllegalArgumentException(ics[i] + " is not visible from class loader");

            sb.append(itf).append(';');
        }

        // use interface class name list as key.
        // 拼接所有的接口名称后 toString作为key
        String key = sb.toString();

        // get cache by class loader.

        Map<String, Object> cache;
        synchronized (ProxyCacheMap) {
            // key 为classLoader value为cache
            cache = ProxyCacheMap.get(cl);
            if (cache == null) {
                cache = new HashMap<String, Object>();
                ProxyCacheMap.put(cl, cache);
            }
        }

        Proxy proxy = null;
        //加锁
        synchronized (cache) {
            do {
                //从缓存中获取 Reference<Proxy> 实例
                //取到了调用get方法返回proxy
                Object value = cache.get(key);
                if (value instanceof Reference<?>) {
                    proxy = (Proxy) ((Reference<?>) value).get();
                    if (proxy != null)
                        return proxy;
                }
                //并发控制,保证只有一个线程可以后续操作
                if (value == PendingGenerationMarker) {
                    try {
                        cache.wait();
                    } catch (InterruptedException e) {
                    }
                } else {
                    cache.put(key, PendingGenerationMarker);
                    break;
                }
            }
            while (true);
        }
        //id自增器
        long id = PROXY_CLASS_COUNTER.getAndIncrement();
        String pkg = null;
        //代理类
        ClassGenerator ccp = null;
        //Proxy实现类创建ccp的对象
        ClassGenerator ccm = null;
        try {
            // 使用当前ClassLoader创建 ClassGenerator 对象,
            ccp = ClassGenerator.newInstance(cl);
            Set<String> worked = new HashSet<String>();
            List<Method> methods = new ArrayList<Method>();
            for (int i = 0; i < ics.length; i++) {
                //如果ics不是public的接口,则需要判断接口是否同包
                if (!Modifier.isPublic(ics[i].getModifiers())) {
                    //获取包名称
                    String npkg = ics[i].getPackage().getName();
                    if (pkg == null) {
                        //赋值pkg
                        pkg = npkg;
                    } else {
                        if (!pkg.equals(npkg))
                            throw new IllegalArgumentException("non-public interfaces from different packages");
                    }
                }
                //添加接口到ccp中
                ccp.addInterface(ics[i]);
                //遍历接口的方法
                for (Method method : ics[i].getMethods()) {
                    //获取方法签名
                    String desc = ReflectUtils.getDesc(method);
                    // 如果方法描述字符串已在 worked 中,则忽略。考虑这种情况,
                    // A 接口和 B 接口中包含一个完全相同的方法
                    if (worked.contains(desc))
                        continue;
                    worked.add(desc);

                    int ix = methods.size();
                    //获取方法返回值
                    Class<?> rt = method.getReturnType();
                    //获取方法的参数列表
                    Class<?>[] pts = method.getParameterTypes();
                    // 生成 Object[] args = new Object[1...N]
                    StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];");
                    for (int j = 0; j < pts.length; j++)
                        // 生成 args[1...N] = ($w)$1...N;
                        code.append(" args[").append(j).append("] = ($w)$").append(j + 1).append(";");
                    // 生成 InvokerHandler 接口的 invoker 方法调用语句,如下:
                    // 生成 InvokerHandler 接口的 invoker 方法调用语句,如下
                    code.append(" Object ret = handler.invoke(this, methods[" + ix + "], args);");
                    // 返回值不为 void
                    if (!Void.TYPE.equals(rt))
                        // 生成返回语句,形如 return (java.lang.String) ret;
                        code.append(" return ").append(asArgument(rt, "ret")).append(";");

                    methods.add(method);
                    // 添加方法名、访问控制符、参数列表、方法代码等信息到 ClassGenerator 中
                    // 说白了就是拼接成为public Integer getName(Integer arg0){...}这种代码字符串
                    ccp.addMethod(method.getName(), method.getModifiers(), rt, pts, method.getExceptionTypes(), code.toString());
                }
            }

            if (pkg == null)
                pkg = PACKAGE_NAME;

            // create ProxyInstance class.
            //  构建接口代理类名称:pkg + ".proxy" + id,比如 org.apache.dubbo.proxy0
            String pcn = pkg + ".proxy" + id;
            //设置className
            ccp.setClassName(pcn);
            //添加静态成员变量
            ccp.addField("public static java.lang.reflect.Method[] methods;");
            //生成 private java.lang.reflect.InvocationHandler handler;
            ccp.addField("private " + InvocationHandler.class.getName() + " handler;");
            // 为接口代理类添加带有 InvocationHandler 参数的构造方法,比如:
            // porxy0(java.lang.reflect.InvocationHandler arg0) {
            //     handler=$1;
            // }
            ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{InvocationHandler.class}, new Class<?>[0], "handler=$1;");
            //添加默认构造方法
            ccp.addDefaultConstructor();
            //生成接口代理类的对象
            Class<?> clazz = ccp.toClass();
            //赋值methods属性
            clazz.getField("methods").set(null, methods.toArray(new Method[0]));
            // create Proxy class.
            String fcn = Proxy.class.getName() + id;
            //构建 Proxy 子类名称,比如 Proxy1,Proxy2 等
            ccm = ClassGenerator.newInstance(cl);
            ccm.setClassName(fcn);
            ccm.addDefaultConstructor();
            ccm.setSuperClass(Proxy.class);
            // 为 Proxy 的抽象方法 newInstance 生成实现代码,形如:
            // public Object newInstance(java.lang.reflect.InvocationHandler h) {
            //     return new org.apache.dubbo.proxy0($1);
            // }
            ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");
            // 通过反射创建 Proxy 实例
            Class<?> pc = ccm.toClass();
            proxy = (Proxy) pc.newInstance();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            // release ClassGenerator
            if (ccp != null)
                ccp.release();
            if (ccm != null)
                ccm.release();
            synchronized (cache) {
                if (proxy == null)
                    cache.remove(key);
                else
                    // 写缓存
                    cache.put(key, new WeakReference<Proxy>(proxy));
                //唤醒其他等待线程
                cache.notifyAll();
            }
        }
        return proxy;
    }
  • 1.首先是接口数组的判断逻辑,如果不是接口,或者接口不存在抛出异常
  • 2.由classLoader为key取得 一个cache Map<String,Object> key为接口数组拼接的字符串(例如"HelloService;EchoService"),Value为Proxy对象,如果没有找到classLoader的cache,则创建一个
  • 3.根据key--接口数组拼接的字符串(例如"HelloService;EchoService")从cache中获取Proxy的实例获取到了直接返回,获取不到,循环加锁直到成功
  • 4.使用javaassist创建加载代理类例如proxy0,和Proxy类的实现类Proxy0。其中Proxy0实现了Proxy类,用于创建proxy0对象

proxy0.java

一般的proxy0的代码类似:

package org.apache.dubbo.common.bytecode;

public class proxy0 implements org.apache.dubbo.demo.DemoService {

    public static java.lang.reflect.Method[] methods;

    private java.lang.reflect.InvocationHandler handler;

    public proxy0() {
    }

    public proxy0(java.lang.reflect.InvocationHandler arg0) {
        handler = $1;
    }

    public java.lang.String sayHello(java.lang.String arg0) {
        Object[] args = new Object[1];
        args[0] = ($w) $1;
        Object ret = handler.invoke(this, methods[0], args);
        return (java.lang.String) ret;
    }
}

InvokerInvocationHandler

该类实现了jdk的接口InvocationHandler,主要用户代理对象的方法调用的执行,服务消费方的方法调用,最后都是通过该类的invoke实现的。

public class InvokerInvocationHandler implements InvocationHandler {

    private final Invoker<?> invoker;

    public InvokerInvocationHandler(Invoker<?> handler) {
        this.invoker = handler;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(invoker, args);
        }
        if ("toString".equals(methodName) && parameterTypes.length == 0) {
            return invoker.toString();
        }
        if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
            return invoker.hashCode();
        }
        if ("equals".equals(methodName) && parameterTypes.length == 1) {
            return invoker.equals(args[0]);
        }
        return invoker.invoke(new RpcInvocation(method, args)).recreate();
    }

}

关于调用流程我们放到后面分析~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值