开发利器Hutool之MapProxy的妙用

目前公司项目中主要采用Hutool作为项目的工具包,相对于google的guava, hutool的工具类采用中文注释,更加符合国人使用。所谓知己知彼,我们需要了解Hutool都具有什么样的功能,才能够最大化发挥它的价值。

目前公司项目中主要采用Hutool作为项目的工具包,相对于google的guava, hutool的工具类采用中文注释,更加符合国人使用。所谓知己知彼,我们需要了解Hutool都具有什么样的功能,才能够最大化发挥它的价值。

概述

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

目前公司项目中主要采用Hutool作为项目的工具包,相对于google的guava, hutool的工具类采用中文注释,更加符合国人使用。所谓知己知彼,我们需要了解Hutool都具有什么样的功能,才能够最大化发挥它的价值。

本文主要就hutool 5.8.8版本中MapProxy的使用。

场景引入

其实Map在get的时候是比较危险的,你可能不知道它是什么类型,需要进行强制,举个例子如下:

@Test
public void testMapProxy1() {
Map<String, Object> userMap = MapUtil.newHashMap(16);
userMap.put("username", "alvin");
userMap.put("age", 20);

// 使用map的时候, 需要进行强转,一旦类型错误,会报错
String age = (String)userMap.get("age");
}

运行结果:

图片

那有什么更好的解决方案吗?Hutool提供了一种解决方案给我们。

MapProxy使用

依赖引入

<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.8</version>
</dependency>

定义一个可访问接口

interface MapUser {
String getUsername();

Integer getAge();

MapUser setAge(Integer age);
}

通过MapProxy访问

@Test
public void testMapProxy2() {
Map<String, Object> userMap = MapUtil.newHashMap(16);
userMap.put("username", "alvin");
userMap.put("age", 20);

MapProxy mapProxy = MapProxy.create(userMap);
Integer age = mapProxy.getInt("age", 18);
Assert.assertTrue(age == 20);

// 通过代理的方式
MapUser mapUser = mapProxy.toProxyBean(MapUser.class);
// 后续访问会变的更加安全
Assert.assertTrue(mapUser.getAge() == 20);

mapUser.setAge(30);
Assert.assertTrue(mapUser.getAge() == 30);
}

MapProxy源码解析

Map代理,提供各种getXXX方法,并提供默认值支持,它的类结构图如下:

图片

  • 实现了OptNullBasicTypeFromObjectGetter接口, 提供了基本类型的get, 在不提供默认值的情况下, 如果值不存在或获取错误,返回null, 比如:mapProxy.getInt("age", 18)
  • 实现了InvocationHandler接口,支持jdk的动态代理,生成代理对象。
public <T> T toProxyBean(Class<T> interfaceClass) {
return (T) Proxy.newProxyInstance(ClassLoaderUtil.getClassLoader(), new Class<?>[]{interfaceClass}, this);
}
  • toProxyBean方法就是生成代理对象,最终会调用代理类的invoke方法,这里的代理类就是MapProxy本身。
public Object invoke(Object proxy, Method method, Object[] args) {
final Class<?>[] parameterTypes = method.getParameterTypes();
// 如果调用方法参数为空
if (ArrayUtil.isEmpty(parameterTypes)) {
final Class<?> returnType = method.getReturnType();
// 方法返回值不是void
if (void.class != returnType) {
// 匹配Getter
final String methodName = method.getName();
String fieldName = null;
if (methodName.startsWith("get")) {
// 匹配getXXX
fieldName = StrUtil.removePreAndLowerFirst(methodName, 3);
} else if (BooleanUtil.isBoolean(returnType) && methodName.startsWith("is")) {
// 匹配isXXX
fieldName = StrUtil.removePreAndLowerFirst(methodName, 2);
}else if ("hashCode".equals(methodName)) {
return this.hashCode();
} else if ("toString".equals(methodName)) {
return this.toString();
}

if (StrUtil.isNotBlank(fieldName)) {
if (false == this.containsKey(fieldName)) {
// 驼峰不存在转下划线尝试
fieldName = StrUtil.toUnderlineCase(fieldName);
}
return Convert.convert(method.getGenericReturnType(), this.get(fieldName));
}
}

// 如果方法参数不为空
} else if (1 == parameterTypes.length) {
// 匹配Setter
final String methodName = method.getName();
if (methodName.startsWith("set")) {
final String fieldName = StrUtil.removePreAndLowerFirst(methodName, 3);
if (StrUtil.isNotBlank(fieldName)) {
this.put(fieldName, args[0]);
final Class<?> returnType = method.getReturnType();
// 判断返回类型是不是代理类的实例
if(returnType.isInstance(proxy)){
return proxy;
}
}
} else if ("equals".equals(methodName)) {
return this.equals(args[0]);
}
}

throw new UnsupportedOperationException(method.toGenericString());
}

总结

本文主要讲解了Hutool中的MapProxy类的使用,希望对大家有帮助。

©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经

(0)
打赏 微信扫码打赏 微信扫码打赏 支付宝扫码打赏 支付宝扫码打赏
清一色的头像清一色管理团队
上一篇 2023年5月6日 21:50
下一篇 2023年5月6日 21:50

相关推荐

发表评论

登录后才能评论

联系我们

在线咨询:1643011589-QQbutton

手机:13798586780

QQ/微信:1074760229

QQ群:551893940

工作时间:工作日9:00-18:00,节假日休息

关注微信