diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4a991be7a..6eb3c6e4d 100644
--- a/CHANGELOG.md
+++ b/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)
diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml
index dc1a47ffe..b1363d249 100644
--- a/hutool-extra/pom.xml
+++ b/hutool-extra/pom.xml
@@ -31,6 +31,7 @@
5.1.1
4.0.1
2.3.1.RELEASE
+ 3.3.0
@@ -232,6 +233,13 @@
1.1.8
true
+
+ cglib
+ cglib
+ ${cglib.version}
+ compile
+ true
+
org.springframework.boot
spring-boot-starter-test
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/cglib/BeanCopierCache.java b/hutool-extra/src/main/java/cn/hutool/extra/cglib/BeanCopierCache.java
new file mode 100644
index 000000000..7378b9090
--- /dev/null
+++ b/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属性缓存
+ * 缓存用于防止多次反射造成的性能问题
+ *
+ * @author Looly
+ * @since 5.4.1
+ */
+public enum BeanCopierCache {
+ INSTANCE;
+
+ private final SimpleCache 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 supplier) {
+ return this.cache.get(StrUtil.format("{}_{}", srcClass.getName(), srcClass.getName()), supplier);
+ }
+}
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/cglib/CglibUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/cglib/CglibUtil.java
new file mode 100644
index 000000000..a9dedf1db
--- /dev/null
+++ b/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对象属性到目标类型
+ * 此方法通过指定目标类型自动创建之,然后拷贝属性
+ *
+ * @param 目标对象类型
+ * @param source 源bean对象
+ * @param targetClass 目标bean类,自动实例化此对象
+ */
+ public static T copy(Object source, Class targetClass) {
+ return copy(source, targetClass, null);
+ }
+
+ /**
+ * 拷贝Bean对象属性
+ * 此方法通过指定目标类型自动创建之,然后拷贝属性
+ *
+ * @param 目标对象类型
+ * @param source 源bean对象
+ * @param targetClass 目标bean类,自动实例化此对象
+ * @param converter 转换器,无需可传{@code null}
+ */
+ public static T copy(Object source, Class 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);
+ }
+}
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/cglib/package-info.java b/hutool-extra/src/main/java/cn/hutool/extra/cglib/package-info.java
new file mode 100644
index 000000000..7b5bba83d
--- /dev/null
+++ b/hutool-extra/src/main/java/cn/hutool/extra/cglib/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * Cglib库方法封装
+ *
+ * @author looly
+ *
+ */
+package cn.hutool.extra.cglib;
\ No newline at end of file
diff --git a/hutool-extra/src/test/java/cn/hutool/extra/cglib/CglibUtilTest.java b/hutool-extra/src/test/java/cn/hutool/extra/cglib/CglibUtilTest.java
new file mode 100644
index 000000000..8994bd6aa
--- /dev/null
+++ b/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;
+ }
+}