JSON多层级数据自动映射值优化

JSON多层级数据自动映射值优化


Spring boot装载模板代码工程中,JSON多层级数据自动映射值只是简单封装JsonPath,对DTO的声明字段做foreach轮询,检查字段注解@JPath,然后从JsonPath的解析缓存中读取@JPath注解的映射路径值,调用ReadContext.read方法取值,按照类型设置对应字段的值;之前,寻找反射的优化时,看到过jdk7新增的MethodHandles用于优化反射,就试试用MethodHandles优化一下;反射在后续更新版本中也借鉴了MethodHandles的一些功能,性能也有一定的提升。

Field

field的set值方法根据字段查找UnsafeFieldAccessorImpl对应的类型实现方法后,在底层调用Unsafe.putObject方法。
在这里插入图片描述

MethodHandles

在原来封装的方法上做如下改动:


	static MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();

	private static <T> void setValueAdvance(Object obj, Field field, T dto) {
        try {
            field.setAccessible(true);
            MethodHandle methodHandle = publicLookup.unreflectSetter(field);
            if (obj != null) {
                if (obj instanceof String) {
                    methodHandle.invoke(dto, typeStrategyMap.get(obj.getClass()).transformType(obj, field.getType()));
                } else if (obj instanceof Map) {
                    Map value = (Map) obj;
                    Object v = JSONObject.toJavaObject(new JSONObject(value), field.getType());
                    methodHandle.invoke(dto, v);
                } else if (obj instanceof Integer) {
                    methodHandle.invoke(dto, typeStrategyMap.get(obj.getClass()).transformType(obj, field.getType()));
                } else if (obj instanceof Long) {
                    methodHandle.invoke(dto, typeStrategyMap.get(obj.getClass()).transformType(obj, field.getType()));
                } else if (obj instanceof Double) {
                    methodHandle.invoke(dto, typeStrategyMap.get(obj.getClass()).transformType(obj, field.getType()));
                } else if (obj instanceof Date) {
                    Date value = (Date) obj;
                    methodHandle.invoke(dto, value);
                } else if (obj instanceof JSONArray) {
                    JSONArray value = (JSONArray) obj;
                    if (field.getType().equals(String.class)) {
                        methodHandle.invoke(dto, value.toJSONString());
                    } else {
                        Type genericType = field.getGenericType();
                        if (genericType instanceof ParameterizedType) {
                            ParameterizedType pt = (ParameterizedType) genericType;
                            // 得到泛型里的class类型对象
                            Class<?> actualTypeArgument = (Class<?>) pt.getActualTypeArguments()[0];
                            List values = com.alibaba.fastjson.JSONArray.parseArray(value.toJSONString(), actualTypeArgument);
                            methodHandle.invoke(dto, values);
                        } else {
                            methodHandle.invoke(dto, value);
                        }
                    }
                } else if (obj instanceof List) {
                    List value = (List) obj;
                    methodHandle.invoke(dto, value);
                } else if (obj instanceof JSONObject) {
                    JSONObject value = (JSONObject) obj;
                    if (field.getType().equals(String.class)) {
                        methodHandle.invoke(dto, value.toJSONString());
                    } else {
                        methodHandle.invoke(dto, value);
                    }
                } else if (obj instanceof Boolean) {
                    Boolean value = (Boolean) obj;
                    if (field.getType().equals(Integer.class)) {
                        methodHandle.invoke(dto, value ? 1 : 0);
                    } else {
                        methodHandle.invoke(dto, value);
                    }
                } else if (obj instanceof BigDecimal) {
                    methodHandle.invoke(dto, typeStrategyMap.get(obj.getClass()).transformType(obj, field.getType()));
                }
            }
        } catch (Throwable iae) {
            iae.printStackTrace();
        }
    }

使用JMH工具做测试:

/**
 * Fork 1个进程进行测试
 * 平均时间
 * JIT预热
 * 迭代10次,每次5s
 * 结果所使用的时间单位
 */
@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 3)
@Measurement(iterations = 10, time = 5)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Threads(10)
public class PathUtilBenchmark {

    static String DATA = "{\"reply_count\":111111,\"com\":\"OptaPlanner是一个开源的轻量级、可嵌入的约束满足引擎!!!\",\"co\":10000000,\"desc\":\"OptaPlanner是一个开源的轻量级、可嵌入的约束满足引擎,可求解规划问题,100%由Java编写,可以在任何JVM上运行,也可以在Maven中央存储库中使用、支持多种平台下载\",\"comment\":\"OptaPlanner是一个开源的轻量级、可嵌入的约束满足引擎,可求解规划问题,100%由Java编写,可以在任何JVM上运行,也可以在Maven中央存储库中使用、支持多种平台下载\"}";

    @Benchmark
    public AdvanceDTO parse() {
        return JsonPathParseUtil.Json2DTO(DATA, AdvanceDTO.class);
    }

    @Benchmark
    public AdvanceDTO parseAdvance() {
        return JsonPathParseUtil.Json2DTOAdvance(DATA, AdvanceDTO.class);
    }

    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(PathUtilBenchmark.class.getSimpleName())
                .result("./result-mh-ex.json")
                .resultFormat(ResultFormatType.JSON)
                .build();
        new Runner(options).run();
    }

}


JMH在测试时,不能用debug模式运行,只能run,执行结果情况如下:
5个线程
![](https://img-blog.csdnimg.cn/53090731a66d4e6e85c0d827d891b598.png
10个线程
在这里插入图片描述
在这里插入图片描述

结果分析

从测试看,性能上确实有提升!跟踪debug:

DirectMethodHandle dmh = DirectMethodHandle.make(refc, field);

返现都会调用Unsafe的putObject的方法,但是,MethodHandles通过LambdaForm构建, LambdaForm是MethodHandles在虚拟机下执行流程的具体实现(LambdaForm是受到lambda的启发而产生的,并不是lambda的实现方式)。非常量类型的MethodHandle 在运行时分发,但运行时分发不能被JIT优化,性能上是有所损失的。LambdaForm是用来解决这一问题的。粗略的说,LambdaForm所代表的字节码可以被JIT优化。因此在非常量类型的MethodHandle变为高性能的调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值