dubbo调用mock
同理,为了实现dubbo的mock,也是要在dubbo调用的过程中添加拦截器
dubbo原始的执行拦截器
Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker))
这里代码写死了,没办法了,只能将整个JavassistProxyFactory 替换掉
public class JavassistProxyFactory extends AbstractProxyFactory {
@Override
@SuppressWarnings("unchecked")
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
@Override
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
// TODO Wrapper cannot handle this scenario correctly: the classname contains '$'
final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
return new AbstractProxyInvoker<T>(proxy, type, url) {
@Override
protected Object doInvoke(T proxy, String methodName,
Class<?>[] parameterTypes,
Object[] arguments) throws Throwable {
return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
}
};
}
}
覆盖默认代理类
在项目 \src\test\resources\META-INF\dubbo\internal下增加文件org.apache.dubbo.rpc.ProxyFactory,增加自定义代理类
localMockProxy=com.xxx.RemoteResultAdaptDubboProxyFactory
@Adaptive
public class RemoteResultAdaptDubboProxyFactory extends JavassistProxyFactory {
@Override
@SuppressWarnings("unchecked")
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
InvokerInvocationHandler invokerInvocationHandler = new InvokerInvocationHandler(invoker);
//自定义实现拦截类
RemoteResultInvocationHandler remoteResultInvocationHandler = new RemoteResultInvocationHandler(invokerInvocationHandler);
//创建动态代理对象
return (T) Proxy.getProxy(interfaces).newInstance(remoteResultInvocationHandler);
}
@Override
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
return super.getInvoker(proxy, type, url);
}
}
自定义拦截器
public class RemoteResultInvocationHandler implements InvocationHandler {
public static final Logger logger = LoggerFactory.getLogger(RemoteResultInvocationHandler.class);
private InvokerInvocationHandler invokerInvocationHandler;
private Map<String, Integer> callCountMap = Maps.newHashMap();
public RemoteResultInvocationHandler(InvokerInvocationHandler invokerInvocationHandler) {
this.invokerInvocationHandler = invokerInvocationHandler;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
CustMethod methodInfo = getInvokeInfo(method);
methodInfo.name = method.getName();
String methodName = buildFileName(methodInfo);
Function<String, Object> mockFunction = filePath -> getMockReturnType(filePath, methodInfo.returnType);
Function remoteFunction = s -> {
try {
return invokerInvocationHandler.invoke(proxy, method, args);
} catch (Throwable e) {
logger.error("methodName={} dubbo remote error", methodName, e);
throw new RuntimeException(e);
}
};
Object result = TestFileHelper.getResult(methodName, mockFunction, remoteFunction);
return result;
}
private String buildFileName(CustMethod method) {
String className = method.className;
String methodName = method.name;
String fileName = className.substring(className.lastIndexOf(".") + 1) + "_" + methodName;
return fileName;
}
private CustMethod getInvokeInfo(Method method) {
CustMethod invokeInfo = getInvokeMethodInfo(method);
if (invokeInfo != null) {
invokeInfo.name = method.getName();
return invokeInfo;
}
invokeInfo = new CustMethod();
invokeInfo.className = method.getDeclaringClass().getName();
invokeInfo.name = method.getName();
invokeInfo.returnType = method.getReturnType();
return invokeInfo;
}
// fastjson 麻烦,还是建议用Gson
public static Object getMockReturnType(String filePath, Object type) {
String result = TestFileHelper.readFile(filePath);
if (type == null) {
return result;
}
if (type instanceof Class) {
Class<?> aClass = (Class<?>) type;
if (aClass.isAssignableFrom(List.class)) {
Object object = JSONObject.parseArray(result, aClass);
return object;
} else {
Object object = JSONObject.parseObject(result, aClass);
return object;
}
} else if (type instanceof Type[]) {
if (((Type[])type).length > 1) {
Object object = JSONObject.parseObject(result, ((Type[])type)[1]);
return object;
}else {
Object object = JSONObject.parseObject(result, ((Type[])type)[0], ParserConfig.global);
return object;
}
}
return result;
}
private CustMethod getInvokeMethodInfo(Method method) {
try {
CustMethod custMethod = new CustMethod();
Object invoker = getDeclaredField(this.invokerInvocationHandler, "invoker");
if (invoker != null) {
Class aClass = ((MigrationInvoker) invoker).getInterface();
ClassRepository genericInfo = (ClassRepository) getDeclaredField(aClass, "genericInfo");
if (genericInfo != null && ArrayUtils.isNotEmpty(genericInfo.getSuperInterfaces())) {
Type superInterface = genericInfo.getSuperInterfaces()[0];
ParameterizedTypeImpl parameterizedType = (ParameterizedTypeImpl) superInterface;
Type actualTypeArgument = parameterizedType.getActualTypeArguments()[1];
custMethod.returnType = actualTypeArgument;
custMethod.className = aClass.getName();
return custMethod;
}else {
String protocolServiceKey = (String) getDeclaredField(this.invokerInvocationHandler, "protocolServiceKey");
RpcInvocation rpcInvocation = new RpcInvocation(method, aClass.getName(), protocolServiceKey, method.getParameterTypes());
custMethod.returnType = rpcInvocation.getReturnTypes();
custMethod.className = aClass.getName();
return custMethod;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
class CustMethod {
public String name;
public Object returnType;
public String className;
}
public static Object getDeclaredField(Object obj, String fieldName){
try {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true); // 设置访问权限,因为"name"是私有属性
return field.get(obj); // 通过反射获得"employee"的"name"属性的值
}catch(Exception e) {
e.printStackTrace();
}
return null;
}
}