package org.zbus.client.rpc; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.zbus.common.logging.Logger; import org.zbus.common.logging.LoggerFactory; /** * * * @author 洪磊明(rushmore) * */ public class RpcProxy { private static final Logger log = LoggerFactory.getLogger(RpcProxy.class); private static Constructor<RpcInvoker> rpcInvokerCtor; private static Map<String,RpcInvoker> rpcInvokerCache = new ConcurrentHashMap<String, RpcInvoker>(); static { try { rpcInvokerCtor = RpcInvoker.class.getConstructor(new Class[] {Rpc.class }); } catch (Exception e) { log.error(e.getMessage(), e); } } @SuppressWarnings("unchecked") public static <T> T getService(Class<T> api, RpcConfig config) throws Exception { String mq = config.getMq(); if(mq == null){ throw new IllegalArgumentException("Missing argument mq"); } String module = config.getModule(); if(module == null ||module.trim().length()==0){ module = api.getSimpleName(); config.setModule(module); } String encoding = config.getEncoding(); int timeout = config.getTimeout(); String accessToken = config.getAccessToken(); String registerToken = config.getRegisterToken(); String cacheKey = String.format( "mq=%s&&module=%s&&encoding=%s&&timeout=%d&&accessToken=%s&®isterToken=%s", mq, module, encoding, timeout, accessToken,registerToken); RpcInvoker rpcInvoker = rpcInvokerCache.get(cacheKey); Class<T>[] interfaces = new Class[] { api }; if(rpcInvoker == null){ Rpc rpc = new Rpc(config); rpcInvoker = rpcInvokerCtor.newInstance(rpc); rpcInvokerCache.put(cacheKey, rpcInvoker); } ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); return (T) Proxy.newProxyInstance(classLoader, interfaces, rpcInvoker); } } class RpcInvoker implements InvocationHandler { private Rpc rpc; private static final Object REMOTE_METHOD_CALL = new Object(); public RpcInvoker(Rpc rpc) { this.rpc = rpc; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(args == null){ args = new Object[0]; } Object value = handleLocalMethod(proxy, method, args); if (value != REMOTE_METHOD_CALL) return value; Class<?> returnType = method.getReturnType(); return rpc.invokeSyncWithType(returnType, method.getName(),method.getParameterTypes(), args); } protected Object handleLocalMethod(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); Class<?>[] params = method.getParameterTypes(); if (methodName.equals("equals") && params.length == 1 && params[0].equals(Object.class)) { Object value0 = args[0]; if (value0 == null || !Proxy.isProxyClass(value0.getClass())) return new Boolean(false); RpcInvoker handler = (RpcInvoker) Proxy.getInvocationHandler(value0); return new Boolean(this.rpc.equals(handler.rpc)); } else if (methodName.equals("hashCode") && params.length == 0) { return new Integer(this.rpc.hashCode()); } else if (methodName.equals("toString") && params.length == 0) { return "RpcInvoker[" + this.rpc + "]"; } return REMOTE_METHOD_CALL; } }