1. 程式人生 > >Dubbo原理實現之代理接口的定義

Dubbo原理實現之代理接口的定義

inf extc apt ride pan hand i++ rri ada

  Dubbo有很多的實現采用了代碼模式,Dubbo由代理工廠ProxyFactory對象創建代理對象。

  ProxyFactory接口的定義如下:

@SPI("javassist")
public interface ProxyFactory {

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

    
/** * create 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; }

  @SPI指定默認使用javassist字節碼技術來生成代理對象,接口定義了生成代理對象的方法getProxy, 入參是invoker對象,接口定義了獲取invoker對象, invoker對象是個可執行對象,這裏inovker對象的invoke方法其實執行的是根據url獲取的方法對第一個入參的實體對象的調用,即:如果url的得知調用方法sayHello, 入參proxy為空Test對象實現test,那invoker.invoke()就是test.sayHello()。

  代理工廠的實現類圖如下:

技術分享圖片  

  AbstractProxyFactory: 代理工廠的公共抽象, 這裏抽象實現主要是獲取需要代理的接口,代理接口可以在設置在url中,key為interfaces, 如果是多個接口用逗號分隔, 如果沒有在url中指定,獲取invoke接口和EchoService接口

public <T> T getProxy(Invoker<T> invoker) 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) { interfaces = new Class<?>[types.length + 2]; interfaces[0] = invoker.getInterface(); interfaces[1] = EchoService.class; for (int i = 0; i < types.length; i++) { interfaces[i + 1] = ReflectUtils.forName(types[i]); } } } if (interfaces == null) { interfaces = new Class<?>[]{invoker.getInterface(), EchoService.class}; } return getProxy(invoker, interfaces); }

  JdkProxyFactory: 利用jdk動態代理來創建代理,實現比較簡單

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

  InvokerInvocationHandler是jdk動態代理創建一定要構建的參數,這裏它的invoke方法只是簡單的調用了invoker.invoke方法, Invoker在dubbo中代表一個可執行體,一切都向它靠攏。

  獲取invoker對象

public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        return new AbstractProxyInvoker<T>(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName,
                                      Class<?>[] parameterTypes,
                                      Object[] arguments) throws Throwable {
                Method method = proxy.getClass().getMethod(methodName, parameterTypes);
                return method.invoke(proxy, arguments);
            }
        };
    }

  這裏創建的 Invoker對象,執行invoke方法,其實就是利用反射技術結合入參執行對應對象的對應方法。

Dubbo原理實現之代理接口的定義