Sofa之Proxy

    Sofa-rpc的版本5.6.1

    RPC調用,基本都會涉及到代理,通過代理封裝接口的實現。

    如下Proxy接口就是Sofa中對代理的抽象,具體的實現類有JDK代理、javassist實現代理、bytebuddy實現代理。

    List-1

@Extensible
public interface Proxy {

    /**
     * 生成代理對象
     *
     * @param interfaceClass 接口類
     * @param proxyInvoker   Invoker
     * @param <T>            類型
     * @return 代理對象
     */
    <T> T getProxy(Class<T> interfaceClass, Invoker proxyInvoker);

    /**
     * 從代理對象裏解析Invoker
     *
     * @param proxyObject 代理對象
     * @return Invoker
     */
    Invoker getInvoker(Object proxyObject);
}

    JDKProxy如下,是JDK代理的實現,代理了接口,具體實現在JDKInvocationHandler中

    List-2

@Extension("jdk")
public class JDKProxy implements Proxy {

    @Override
    public <T> T getProxy(Class<T> interfaceClass, Invoker proxyInvoker) {
        InvocationHandler handler = new JDKInvocationHandler(interfaceClass, proxyInvoker);
        ClassLoader classLoader = ClassLoaderUtils.getCurrentClassLoader();
        T result = (T) java.lang.reflect.Proxy.newProxyInstance(classLoader,
            new Class[] { interfaceClass }, handler);
        return result;
    }

    @Override
    public Invoker getInvoker(Object proxyObject) {
        return parseInvoker(proxyObject);
    }

    /**
     * Parse proxy invoker from proxy object
     *
     * @param proxyObject Proxy object
     * @return proxy invoker
     */
    public static Invoker parseInvoker(Object proxyObject) {
        InvocationHandler handler = java.lang.reflect.Proxy.getInvocationHandler(proxyObject);
        if (handler instanceof JDKInvocationHandler) {
            return ((JDKInvocationHandler) handler).getProxyInvoker();
        }
        return null;
    }
}

    JDKInvocationHandler的實現如下List-3,將調用的方法簽名封裝到SofaRequest中,之後調用ProxyInvoker.invoke,ProxyInvoker是一個鏈,類似J2EE中的Filter。 返回的SofaResponse,獲取到服務提供者的響應後,如果是異常,則直接拋出,如果結果是Null且是JDK的基礎類,則返回默認值。

  List-3

@Override
public Object invoke(Object proxy, Method method, Object[] paramValues)
    throws Throwable {
    String methodName = method.getName();
    Class[] paramTypes = method.getParameterTypes();
    if ("toString".equals(methodName) && paramTypes.length == 0) {
        return proxyInvoker.toString();
    } else if ("hashCode".equals(methodName) && paramTypes.length == 0) {
        return proxyInvoker.hashCode();
    } else if ("equals".equals(methodName) && paramTypes.length == 1) {
        Object another = paramValues[0];
        return proxy == another ||
            (proxy.getClass().isInstance(another) && proxyInvoker.equals(JDKProxy.parseInvoker(another)));
    }
    SofaRequest sofaRequest = MessageBuilder.buildSofaRequest(method.getDeclaringClass(),
        method, paramTypes, paramValues);
    SofaResponse response = proxyInvoker.invoke(sofaRequest);
    if (response.isError()) {
        throw new SofaRpcException(RpcErrorType.SERVER_UNDECLARED_ERROR, response.getErrorMsg());
    }
    Object ret = response.getAppResponse();
    if (ret instanceof Throwable) {
        throw (Throwable) ret;
    } else {
        if (ret == null) {
            return ClassUtils.getDefaultPrimitiveValue(method.getReturnType());
        }
        return ret;
    }
}

    所以重點在於JDKInvocationHandler中的ProxyInvoker的實現。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章