Spring-Utils
Spring 中的工具类
Spring BeanUtils
org.springframework.beans.BeanUtils
public abstract class BeanUtils
extends java.lang.Object
getPropertyDescriptors() 获取全部属性描述符
public static java.beans.PropertyDescriptor[] getPropertyDescriptors(java.lang.Class<?> clazz) throws BeansException
获取一个 Bean 的全部属性描述符
getPropertyDescriptor() 获取指定属性描述符
@Nullable
public static PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String propertyName) throws BeansException
获取指定的属性描述符
copyProperties() 拷贝属性值(浅拷贝)
public static void copyProperties(Object source, Object target) throws BeansException
public static void copyProperties(Object source, Object target, Class<?> editable) throws BeansExceptio
public static void copyProperties(Object source, Object target, String... ignoreProperties) throws BeansExceptio
拷贝属性值,从 source 到 target
原类型和目标类型不需要相同,只要属性名匹配就会拷贝。原类型有但目标类没有的属性会被忽略。
copyProperties 是浅拷贝,只是调用子对象的set方法
如果都是单一的属性,那么不涉及到深拷贝的问题,适合用BeanUtils。
如果有子对象但子对象不需要改动,也可以使用 BeanUtils
editable:只设置 editable 类型指定的属性
ignoreProperties:指定要忽略的属性名数组
方法有一个不足的地方,就是 当 source 里的属性对应的属性值为 null 时,也会覆盖掉 target 里相同属性名的属性,即使target中该属性值已存在且不为null的属性值。
自定义Bean字段比较和拷贝工具类
比较source bean和target bean各个字段,若发生改变则覆盖target bean字段,返回是否有改变
package com.masikkk.utils;
import com.nio.uds.common.utils.Comparators;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.FatalBeanException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
public class MyBeanUtils {
/**
* 比较source bean和target bean各个字段,若发生改变则覆盖target bean字段
* @param source
* @param target
* @param ignoreProperties
* @return 返回是否有字段发生变化
*/
public static boolean copyProperties(Object source, Object target, String... ignoreProperties) {
boolean hasChanged = false;
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Class<?> actualEditable = target.getClass();
PropertyDescriptor[] targetPds = BeanUtils.getPropertyDescriptors(actualEditable);
List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null;
for (PropertyDescriptor targetPd : targetPds) {
Method writeMethod = targetPd.getWriteMethod();
if (writeMethod != null && (ignoreProperties == null || (!ignoreList.contains(targetPd.getName())))) {
PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(source.getClass(), targetPd.getName());
if (sourcePd != null) {
Method readMethod = sourcePd.getReadMethod();
Method targetReadMethod = targetPd.getReadMethod();
if (readMethod != null && (ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType()))) {
try {
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
// 原bean的值
Object sourceValue = readMethod.invoke(source);
// 目标bean的值
Object targetValue = targetReadMethod.invoke(target);
if (!Comparators.equals(sourceValue, targetValue)) {
hasChanged = true;
writeMethod.invoke(target, sourceValue);
}
} catch (Throwable ex) {
throw new FatalBeanException( "Could not copy property '" + targetPd.getName() + "' from source to target", ex);
}
}
}
}
}
return hasChanged;
}
}
Apache BeanUtils
Map 和 Bean 互相转换
1 Map 转 Bean
Map<String, Object> map = new HashMap();
MyBean myBean = new MyBean();
org.apache.commons.beanutils.BeanUtils.populate(myBean, map);
2 Bean 转 Map
commons-beanutils 中的 BeanMap
类继承自 AbstractMap<Object, Object>
,本身就是一个 Map,所以直接 new 一个 BeanMap
传入 object 对象即可。
Map<Object, Object> beanMap = new BeanMap(humanDataVO);
需要添加
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
StopWatch
使用示例
StopWatch stopWatch = new StopWatch("My Stop Watch");
stopWatch.start("initializing");
Thread.sleep(2000); // simulated work
stopWatch.stop();
stopWatch.start("processing");
Thread.sleep(5000); // simulated work
stopWatch.stop();
stopWatch.start("finalizing");
Thread.sleep(3000); // simulated work
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
从 Spring Framework 5.2 开始,以纳秒为单位跟踪和报告运行时间。
DigestUtils
spring-core 包中的 MessageDigest 内部也是使用 jdk 自带的 MessageDigest
String md5Str = DigestUtils.md5DigestAsHex("字符串".getBytes(StandardCharsets.UTF_8));
MultiValueMap
一个 key 中可以存放多个 value 的 Map,类似 Apache-Commons-Collections 中的 MultiValuedMap
@Test
public void testMultiValueMap() {
MultiValueMap<String, String> mvm = new LinkedMultiValueMap<>();
String key1 = "key1";
mvm.add(key1, "value1");
mvm.add(key1, "value2");
List<String> values = mvm.get(key1);
Assertions.assertNotNull(values);
Assertions.assertEquals(2, values.size());
Assertions.assertEquals("value1", mvm.getFirst(key1));
System.out.println(mvm);
}
结果:
{key1=[value1, value2]}
上一篇 Caffeine 缓存
下一篇 MapStruct
页面信息
location:
protocol
: host
: hostname
: origin
: pathname
: href
: document:
referrer
: navigator:
platform
: userAgent
: