Browse Source

add CglibUtil

Looly 5 years ago
parent
commit
b46d99a15a

+ 1 - 0
CHANGELOG.md

@@ -13,6 +13,7 @@
 * 【core  】     Validator修改isCitizenId校验(pr#1032@Github)
 * 【core  】     增加PathUtil和FileNameUtil,分离FileUtil中部分方法
 * 【core  】     改造IndexedComparator,增加InstanceComparator
+* 【extra 】     增加CglibUtil
 
 ### Bug修复#
 * 【poi   】     修复ExcelBase.isXlsx方法判断问题(issue#I1S502@Gitee)

+ 8 - 0
hutool-extra/pom.xml

@@ -31,6 +31,7 @@
 		<emoji-java.version>5.1.1</emoji-java.version>
 		<servlet-api.version>4.0.1</servlet-api.version>
 		<spring-boot.version>2.3.1.RELEASE</spring-boot.version>
+		<cglib.version>3.3.0</cglib.version>
 	</properties>
 
 	<dependencies>
@@ -233,6 +234,13 @@
 			<optional>true</optional>
 		</dependency>
 		<dependency>
+			<groupId>cglib</groupId>
+			<artifactId>cglib</artifactId>
+			<version>${cglib.version}</version>
+			<scope>compile</scope>
+			<optional>true</optional>
+		</dependency>
+		<dependency>
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-test</artifactId>
 			<version>${spring-boot.version}</version>

+ 34 - 0
hutool-extra/src/main/java/cn/hutool/extra/cglib/BeanCopierCache.java

@@ -0,0 +1,34 @@
+package cn.hutool.extra.cglib;
+
+import cn.hutool.core.lang.SimpleCache;
+import cn.hutool.core.lang.func.Func0;
+import cn.hutool.core.util.StrUtil;
+import net.sf.cglib.beans.BeanCopier;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * BeanCopier属性缓存<br>
+ * 缓存用于防止多次反射造成的性能问题
+ *
+ * @author Looly
+ * @since 5.4.1
+ */
+public enum BeanCopierCache {
+	INSTANCE;
+
+	private final SimpleCache<String, BeanCopier> cache = new SimpleCache<>();
+
+	/**
+	 * 获得属性名和{@link PropertyDescriptor}Map映射
+	 *
+	 * @param srcClass    源Bean的类
+	 * @param targetClass 目标Bean的类
+	 * @param supplier    缓存对象产生函数
+	 * @return 属性名和{@link PropertyDescriptor}Map映射
+	 * @since 5.4.1
+	 */
+	public BeanCopier get(Class<?> srcClass, Class<?> targetClass, Func0<BeanCopier> supplier) {
+		return this.cache.get(StrUtil.format("{}_{}", srcClass.getName(), srcClass.getName()), supplier);
+	}
+}

+ 83 - 0
hutool-extra/src/main/java/cn/hutool/extra/cglib/CglibUtil.java

@@ -0,0 +1,83 @@
+package cn.hutool.extra.cglib;
+
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.ReflectUtil;
+import net.sf.cglib.beans.BeanCopier;
+import net.sf.cglib.beans.BeanMap;
+import net.sf.cglib.core.Converter;
+
+/**
+ * Cglib工具类
+ *
+ * @author looly
+ * @since 5.4.1
+ */
+public class CglibUtil {
+
+	/**
+	 * 拷贝Bean对象属性到目标类型<br>
+	 * 此方法通过指定目标类型自动创建之,然后拷贝属性
+	 *
+	 * @param <T>         目标对象类型
+	 * @param source      源bean对象
+	 * @param targetClass 目标bean类,自动实例化此对象
+	 */
+	public static <T> T copy(Object source, Class<T> targetClass) {
+		return copy(source, targetClass, null);
+	}
+
+	/**
+	 * 拷贝Bean对象属性<br>
+	 * 此方法通过指定目标类型自动创建之,然后拷贝属性
+	 *
+	 * @param <T>         目标对象类型
+	 * @param source      源bean对象
+	 * @param targetClass 目标bean类,自动实例化此对象
+	 * @param converter   转换器,无需可传{@code null}
+	 */
+	public static <T> T copy(Object source, Class<T> targetClass, Converter converter) {
+		final T target = ReflectUtil.newInstanceIfPossible(targetClass);
+		copy(source, target);
+		return target;
+	}
+
+	/**
+	 * 拷贝Bean对象属性
+	 *
+	 * @param source 源bean对象
+	 * @param target 目标bean对象
+	 */
+	public static void copy(Object source, Object target) {
+		copy(source, target, null);
+	}
+
+	/**
+	 * 拷贝Bean对象属性
+	 *
+	 * @param source    源bean对象
+	 * @param target    目标bean对象
+	 * @param converter 转换器,无需可传{@code null}
+	 */
+	public static void copy(Object source, Object target, Converter converter) {
+		Assert.notNull(source, "Source bean must be not null.");
+		Assert.notNull(target, "Target bean must be not null.");
+
+		final Class<?> sourceClass = source.getClass();
+		final Class<?> targetClass = target.getClass();
+		final BeanCopier beanCopier = BeanCopierCache.INSTANCE.get(
+				sourceClass, targetClass,
+				() -> BeanCopier.create(sourceClass, targetClass, null != converter));
+
+		beanCopier.copy(source, target, converter);
+	}
+
+	/**
+	 * 将Bean转换为Map
+	 *
+	 * @param bean Bean对象
+	 * @return {@link BeanMap}
+	 */
+	public static BeanMap toMap(Object bean){
+		return BeanMap.create(bean);
+	}
+}

+ 7 - 0
hutool-extra/src/main/java/cn/hutool/extra/cglib/package-info.java

@@ -0,0 +1,7 @@
+/**
+ * Cglib库方法封装
+ * 
+ * @author looly
+ *
+ */
+package cn.hutool.extra.cglib;

+ 31 - 0
hutool-extra/src/test/java/cn/hutool/extra/cglib/CglibUtilTest.java

@@ -0,0 +1,31 @@
+package cn.hutool.extra.cglib;
+
+import lombok.Data;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CglibUtilTest {
+
+	@Test
+	public void copyTest() {
+		SampleBean bean = new SampleBean();
+		bean.setValue("Hello world");
+
+		OtherSampleBean otherBean = new OtherSampleBean();
+		CglibUtil.copy(bean, otherBean);
+		Assert.assertEquals("Hello world", otherBean.getValue());
+
+		OtherSampleBean otherBean2 = CglibUtil.copy(bean, OtherSampleBean.class);
+		Assert.assertEquals("Hello world", otherBean2.getValue());
+	}
+
+	@Data
+	public static class SampleBean {
+		private String value;
+	}
+
+	@Data
+	public static class OtherSampleBean {
+		private String value;
+	}
+}