第10章 Dubbo 代理層的設計與實現(xiàn)

image.png

本節(jié)介紹 Dubbo 十層架構(gòu)中的 Proxy 層。

image.png
  • ProxyFactory:代理工廠接口;
  • StubProxyFactoryWrapper:代理工廠裝飾類(封裝了對 stublocal 的處理邏輯),會在獲取 ProxyFactory 具體子類時進行 AOP;
  • AbstractProxyFactory:代理工廠模板類(封裝了獲取組裝接口的功能,用于創(chuàng)建動態(tài)代理),提供了模板方法;
  • JavassistProxyFactory:基于 Javassist 實現(xiàn)的代理工廠;
  • JdkProxyFactory:基于 JDK 動態(tài)代理實現(xiàn)的代理工廠;
  • AbstractProxyInvoker:最終封裝的代理 Invoker,其子類內(nèi)部發(fā)起真正的調(diào)用;
  • InvokerInvocationHandler:Proxy 發(fā)起調(diào)用時,會調(diào)用該類的 invoke(...),在該 invoke(...) 方法中,默認會調(diào)用 MockClusterInvoker 的 invoke(...),之后一路進行調(diào)用。

一、代理工廠接口 ProxyFactory

@SPI("javassist")
public interface ProxyFactory {
    /**
     * 使用端:consumer
     *
     * 創(chuàng)造一個代理,用于服務引用創(chuàng)建代理
     * @param invoker會被proxy調(diào)用的第一層Invoker,默認是 MockClusterInvoker
     * @return proxy 代理對象
     */
    @Adaptive({Constants.PROXY_KEY})
    <T> T getProxy(Invoker<T> invoker) throws RpcException;

    /**
     * 使用端:provider
     *
     * 創(chuàng)建一個Invoker,默認是代理Invoker -- AbstractProxyInvoker 的子類對象
     * @param <T> 接口 eg. com.alibaba.dubbo.demo.DemoService
     * @param proxy ref實例, eg. emoServiceImpl實例
     * @param type interface eg. com.alibaba.dubbo.demo.DemoService
     * @param url -- 
     *       injvm://127.0.0.1/com.alibaba.dubbo.demo.DemoService?anyhost=true...
     *       registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-provider...&export=dubbo://10.213.11.98:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true...
     * @return invoker,默認是代理Invoker -- AbstractProxyInvoker 的子類對象
     */
    @Adaptive({Constants.PROXY_KEY})
    <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;
}

二、代理工廠裝飾類 StubProxyFactoryWrapper

public class StubProxyFactoryWrapper implements ProxyFactory {
    // 真正的ProxyFactory具體子類(JavassistProxyFactory/JdkProxyFactory)
    private final ProxyFactory proxyFactory;
    
    // 具有父類SPI接口(ProxyFactory)的單參構(gòu)造器,所以該類是一個Wrapper類,會在getExtension獲取ProxyFactory具體子類時進行aop
    public StubProxyFactoryWrapper(ProxyFactory proxyFactory) {
        this.proxyFactory = proxyFactory;
    }

    /**
     * 使用端:consumer
     */
    @Override
    public <T> T getProxy(Invoker<T> invoker) throws RpcException {
        // 1. 調(diào)用 ProxyFactory 獲取代理
        T proxy = proxyFactory.getProxy(invoker);
        // 2. 如果不是泛化接口,處理 stub 和 local
        ...
        return proxy;
    }

    /**
     * 使用端:provider
     */
    @Override
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException {
        return proxyFactory.getInvoker(proxy, type, url);
    }
}

三、代理工廠模板類 AbstractProxyFactory

public abstract class AbstractProxyFactory implements ProxyFactory {
    @Override
    public <T> T getProxy(Invoker<T> invoker) throws RpcException {
        /**
         * 1. 構(gòu)造接口參數(shù),默認只有 invoker.getInterface()(eg. DemoService), EchoService.class 兩個接口
         */
        ...
        Class<?>[] interfaces = new Class<?>[]{invoker.getInterface(), EchoService.class};
        ...

        /**
         * 2. 調(diào)用子類的實現(xiàn)去創(chuàng)建代理
         */
        return getProxy(invoker, interfaces);
    }

    /**
     * 提供給子類的抽象方法
     */
    public abstract <T> T getProxy(Invoker<T> invoker, Class<?>[] types);

}

四、JdkProxyFactory

public class JdkProxyFactory extends AbstractProxyFactory {
    // 使用端:consumer
    @Override
    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        // 使用JDK方式創(chuàng)建Java動態(tài)代理,創(chuàng)建了動態(tài)代理的邏輯處理類 InvokerInvocationHandler,并且傳入了 MockClusterInvoker
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker));
    }

    // 使用端:provider
    @Override
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        // 創(chuàng)建真正的Invoker代理
        return new AbstractProxyInvoker<T>(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName,
                                      Class<?>[] parameterTypes,
                                      Object[] arguments) throws Throwable {
                // 獲取真正的方法Method,proxy=DemoServiceImpl實例
                Method method = proxy.getClass().getMethod(methodName, parameterTypes);
                // 執(zhí)行真正的方法
                return method.invoke(proxy, arguments);
            }
        };
    }
}

五、JavassistProxyFactory

public class JavassistProxyFactory extends AbstractProxyFactory {
    // 使用端:consumer
    @Override
    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        // 使用 com.alibaba.dubbo.common.bytecode.Proxy 創(chuàng)建代理,創(chuàng)建了動態(tài)代理的邏輯處理類 InvokerInvocationHandler,并且傳入了 MockClusterInvoker
        return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }

    // 使用端:provider
    @Override
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        // wrapper:通過動態(tài)生成一個真實的服務提供者(DemoServiceImpl)的wrapper類,來避免反射調(diào)用
        final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass());
        return new AbstractProxyInvoker<T>(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName,
                                      Class<?>[] parameterTypes,
                                      Object[] arguments) throws Throwable {
                // 直接調(diào)用wrapper,wrapper底層調(diào)用DemoServiceImpl
                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };
    }
}

首先來看下 consumer 端:

Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker))

這里首先調(diào)用 Proxy.getProxy(interfaces) 獲取到一個創(chuàng)建代理的工廠類 com.alibaba.dubbo.common.bytecode.Proxy0,如下:

package com.alibaba.dubbo.common.bytecode;

import com.alibaba.dubbo.common.bytecode.ClassGenerator;
import com.alibaba.dubbo.common.bytecode.Proxy;
import com.alibaba.dubbo.common.bytecode.proxy0;
import java.lang.reflect.InvocationHandler;

public class Proxy0 extends Proxy implements ClassGenerator.DC {
    public Object newInstance(InvocationHandler invocationHandler) {
        return new proxy0(invocationHandler);
    }
}

之后調(diào)用了 Proxy0#newInstance 方法,創(chuàng)建了一個 com.alibaba.dubbo.common.bytecode.proxy0 實例,該實例就是最終的 DemoService 的代理對象。

DemoService demoService = (DemoService) context.getBean("demoService");

這里的 demoService 就是上述的 com.alibaba.dubbo.common.bytecode.proxy0 實例。

package com.alibaba.dubbo.common.bytecode;

import com.alibaba.dubbo.common.bytecode.ClassGenerator;
import com.alibaba.dubbo.demo.DemoService;
import com.alibaba.dubbo.rpc.service.EchoService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class proxy0 implements EchoService, DemoService {
    public static Method[] methods;
    private InvocationHandler handler;

    public String sayHello(String string) {
        Object[] arrobject = new Object[]{string};
        Object object = this.handler.invoke(this, methods[0], arrobject);
        return (String)object;
    }

    public Object $echo(Object object) {
        Object[] arrobject = new Object[]{object};
        Object object2 = this.handler.invoke(this, methods[1], arrobject);
        return object2;
    }

    public proxy0() {
    }

    public proxy0(InvocationHandler invocationHandler) {
        this.handler = invocationHandler;
    }
}
  • proxy0 實現(xiàn)的接口就是 AbstractProxyFactory 中獲取的接口;
  • 當調(diào)用 proxy0#sayHello 時,實際上其內(nèi)部執(zhí)行的是 InvokerInvocationHandlerr#invoke,來看一下 InvokerInvocationHandler。

六、代理邏輯處理類 InvokerInvocationHandler

public class InvokerInvocationHandler implements InvocationHandler {
    /**
     * 第一個被Proxy調(diào)用的Invoker,默認為MockClusterInvoker
     */
    private final Invoker<?> invoker;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        ...
        // 1. 創(chuàng)建請求參數(shù)RpcInvocation
        // 2. 執(zhí)行調(diào)用
        // 3. 對調(diào)用結(jié)果進行重建recreate():若響應有異常,直接拋異常;否則返回響應
        return invoker.invoke(new RpcInvocation(method, args)).recreate();
    }
}

七、Invoker代理 AbstractProxyInvoker

public abstract class AbstractProxyInvoker<T> implements Invoker<T> {
    // 真實對象 ref, eg. DemoServiceImpl
    private final T proxy;
    // 接口類型,eg. DemoService
    private final Class<T> type;
    ...
    public AbstractProxyInvoker(T proxy, Class<T> type, URL url) {
        ...
        this.proxy = proxy;
        this.type = type;
        ...
    }
   ...
    /**
     * 進行調(diào)用
     * @param invocation 請求參數(shù)
     * @return 返回結(jié)果
     * @throws RpcException
     */
    @Override
    public Result invoke(Invocation invocation) throws RpcException {
        try {
            // 1. 調(diào)用子類發(fā)起請求
            // 2. 包裝響應為 RpcResult
            return new RpcResult(doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()));
        } catch (InvocationTargetException e) {
            return new RpcResult(e.getTargetException());
        } catch (Throwable e) {
            throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }

    // 子類覆寫的真正調(diào)用的方法
    protected abstract Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable;
}

AbstractProxyInvoker 的子類在 JdkProxyFactory#getInvoker(...)JavassistProxyFactory#getInvoker(...) 中進行創(chuàng)建的,來看下JavassistProxyFactory#getInvoker(...)

    // 使用端:provider
    @Override
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        // wrapper:通過動態(tài)生成一個真實的服務提供者(DemoServiceImpl)的wrapper類,來避免反射調(diào)用
        final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass());
        return new AbstractProxyInvoker<T>(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName,
                                      Class<?>[] parameterTypes,
                                      Object[] arguments) throws Throwable {
                // 直接調(diào)用wrapper,wrapper底層調(diào)用DemoServiceImpl
                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };
    }

再貼下最終生成的 wrapper 類實例(com.alibaba.dubbo.common.bytecode.Wrapper0)。

package com.alibaba.dubbo.common.bytecode;

import com.alibaba.dubbo.common.bytecode.ClassGenerator;
import com.alibaba.dubbo.common.bytecode.NoSuchMethodException;
import com.alibaba.dubbo.common.bytecode.NoSuchPropertyException;
import com.alibaba.dubbo.common.bytecode.Wrapper;
import com.alibaba.dubbo.demo.DemoService;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

public class Wrapper0 extends Wrapper implements ClassGenerator.DC {
    ...
    /**
     * @param object 實現(xiàn)類ref,eg. DemoServiceImpl
     * @param string 方法名稱
     * @param arrclass 參數(shù)類型
     * @param arrobject 參數(shù)值
     * @return 調(diào)用返回值
     * @throws java.lang.reflect.InvocationTargetException
     */
    public Object invokeMethod(Object object, String string, Class[] arrclass, Object[] arrobject) throws InvocationTargetException {
        DemoService demoService;
        try {
            demoService = (DemoService)object;
        } catch (Throwable throwable) {
            throw new IllegalArgumentException(throwable);
        }
        try {
            if ("sayHello".equals(string) && arrclass.length == 1) {
                return demoService.sayHello((String)arrobject[0]);
            }
        } catch (Throwable throwable) {
            throw new InvocationTargetException(throwable);
        }
        throw new NoSuchMethodException(new StringBuffer().append("Not found method \"").append(string).append("\" in class com.alibaba.dubbo.demo.DemoService.").toString());
    }
    ...
}
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容