myrpc 学习笔记-003 Mock 服务代理
项目地址 欢迎访问
笔记总览 myrpc 学习笔记-001 实现简易版 rpc myrpc 学习笔记-002 配置加载 myrpc 学习笔记-003 Mock 服务代理 myrpc 学习笔记-004 序列化实现和 SPI 机制 myrpc 学习笔记-005 注册中心 myrpc 学习笔记-006 自定义协议 myrpc 学习笔记-007 负载均衡 myrpc 学习笔记-008 重试机制 myrpc 学习笔记-009 容错机制 myrpc 学习笔记-0010 启动机制和注解驱动
架构图v3.0.0
- 可通过配置选择是否启动 mock 接口
- 使用 JavaFaker 返回模拟数据
- 支持基础类型、String、Date 以及自定义 POJO 的自动填充

一、需求说明
- 增加
mock配置项,控制是否开启模拟调用 - 开启
mock后,不发起真实RPC远程调用,直接返回模拟数据 - 支持两种实现:
- 简单版:返回类型默认值
- 增强版:使用JavaFaker生成仿真数据(支持基础类型、字符串、日期、自定义POJO)
二、基础实现步骤
1. 新增配置项
在RpcConfig中添加mock开关,默认关闭
▼java复制代码/** * RPC 框架配置 */ @Data public class RpcConfig implements Serializable { // 原有配置... /** * 是否开启 mock(默认 false) */ private boolean mock = false; }
2. 优化服务代理工厂
根据mock配置自动切换真实代理 / Mock代理
▼java复制代码package com.longlong.myrpc.proxy; import com.longlong.myrpc.RpcApplication; import java.lang.reflect.Proxy; /** * 服务代理工厂(支持Mock开关) */ public class ServiceProxyFactory { // 私有构造,禁止实例化 private ServiceProxyFactory() { } /** * 根据服务接口获取代理对象 */ public static <T> T getProxy(Class<T> serviceClass) { // 读取全局配置,自动选择代理 boolean isMock = RpcApplication.getRpcConfig().isMock(); return isMock ? getMockProxy(serviceClass) : getRealProxy(serviceClass); } /** * 真实远程调用代理 */ private static <T> T getRealProxy(Class<T> serviceClass) { return (T) Proxy.newProxyInstance( serviceClass.getClassLoader(), new Class[]{serviceClass}, new ServiceProxy() ); } /** * Mock 模拟代理 */ private static <T> T getMockProxy(Class<T> serviceClass) { return (T) Proxy.newProxyInstance( serviceClass.getClassLoader(), new Class[]{serviceClass}, new MockServiceProxy() ); } }
三、方案1:简单Mock实现(返回默认值)
核心逻辑
根据方法返回值类型,返回Java默认值(基本类型0/false,对象null)
Mock代理类实现
▼java复制代码package com.longlong.myrpc.proxy; import lombok.extern.slf4j.Slf4j; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * Mock 服务代理(JDK 动态代理)- 简单默认值版 */ @Slf4j public class MockServiceProxy implements InvocationHandler { /** * 调用方法时,返回默认 mock 值 */ @Override public Object invoke(Object proxy, Method method, Object[] args) { // 获取方法返回类型 Class<?> returnType = method.getReturnType(); log.info("mock 服务代理, 不发请求,返回默认 mock 数据"); // 返回默认 mock 数据 return getDefaultValue(returnType); } /** * 根据类型返回默认值 */ private Object getDefaultValue(Class<?> type) { // 基础类型 if (type == boolean.class) { return false; } if (type == byte.class) { return (byte) 0; } if (type == short.class) { return (short) 0; } if (type == int.class) { return 0; } if (type == long.class) { return 0L; } if (type == float.class) { return 0.0f; } if (type == double.class) { return 0.0d; } if (type == char.class) { return '\0'; } // 包装类型 & 对象 -> 返回 null return null; } }
四、方案2:增强Mock实现(JavaFaker仿真数据)
1. 引入依赖
使用JavaFaker生成真实感模拟数据
▼xml复制代码<!-- JavaFaker 仿真数据生成 --> <dependency> <groupId>com.github.javafaker</groupId> <artifactId>javafaker</artifactId> <version>1.0.2</version> <scope>compile</scope> </dependency>
2. 增强版Mock代理类
支持:
- 基本类型 + 包装类型
- String、Date
- 自定义POJO自动填充(反射递归赋值)
▼java复制代码package com.longlong.myrpc.proxy; import com.github.javafaker.Faker; import lombok.extern.slf4j.Slf4j; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Date; /** * Mock 服务代理(JavaFaker 增强版) * 支持基础类型、String、Date、自定义 POJO 自动填充 */ @Slf4j public class MockServiceProxy implements InvocationHandler { private final Faker faker = new Faker(); @Override public Object invoke(Object proxy, Method method, Object[] args) { Class<?> returnType = method.getReturnType(); log.info("Mock 代理调用 -> 方法:{}, 返回类型:{}", method.getName(), returnType.getSimpleName()); try { return getFakerValue(returnType); } catch (Exception e) { log.error("Mock数据生成失败", e); return null; } } /** * 根据类型生成仿真数据 */ private Object getFakerValue(Class<?> type) { // 布尔 if (type == boolean.class || type == Boolean.class) { return faker.bool().bool(); } // 字节 if (type == byte.class || type == Byte.class) { return (byte) faker.number().numberBetween(Byte.MIN_VALUE, Byte.MAX_VALUE); } // 短整型 if (type == short.class || type == Short.class) { return (short) faker.number().numberBetween(Short.MIN_VALUE, Short.MAX_VALUE); } // 整型 if (type == int.class || type == Integer.class) { return faker.number().randomDigit(); } // 长整型 if (type == long.class || type == Long.class) { return faker.number().randomNumber(); } // 浮点 if (type == float.class || type == Float.class) { return faker.number().randomDouble(2, 0, 1000); } // 双精度 if (type == double.class || type == Double.class) { return faker.number().randomDouble(2, 0, 10000); } // 字符 if (type == char.class || type == Character.class) { return faker.lorem().character(); } // 字符串 if (type == String.class) { return faker.lorem().word(); } // 日期 if (type == Date.class) { return faker.date().birthday(); } // 自定义POJO(排除JDK内置类) if (!type.isPrimitive() && !type.getName().startsWith("java")) { return handleComplexObject(type); } // 无法处理返回null log.warn("不支持的类型:{},返回null", type.getName()); return null; } /** * 反射填充自定义对象字段 */ private Object handleComplexObject(Class<?> type) { try { // 创建对象实例 Object instance = type.getDeclaredConstructor().newInstance(); Field[] fields = type.getDeclaredFields(); for (Field field : fields) { // 跳过静态、常量字段 int mod = field.getModifiers(); if (java.lang.reflect.Modifier.isStatic(mod) || java.lang.reflect.Modifier.isFinal(mod)) { continue; } field.setAccessible(true); // 递归赋值 Object value = getFakerValue(field.getType()); field.set(instance, value); } return instance; } catch (Exception e) { log.error("POJO填充失败:{}", type.getName(), e); return null; } } }
五、使用方式
1. 配置开启Mock
application.properties
▼properties复制代码rpc.mock=true
2. 代码使用
▼java复制代码// 获取代理(自动根据mock配置选择) UserService userService = ServiceProxyFactory.getProxy(UserService.class); // 调用:开启mock则返回模拟数据,关闭则发起真实RPC调用 User user = userService.getUserById(1L);
六、核心总结
- 配置化控制:通过
mock布尔配置一键开关 - 动态代理:基于JDK动态代理实现无侵入Mock
- 两种方案
- 简单版:轻量、无依赖,返回默认值
- 增强版:JavaFaker生成仿真数据,支持POJO自动填充
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
