diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9605617b6..969d45491 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
### 新特性
* 【core 】 新增WatchServer(issue#440@Github)
* 【core 】 ReflectUtil.getFieldValue支持static(issue#662@Github)
+* 【core 】 改进Bean判断和注入逻辑:支持public字段注入(issue#I1689L@Gitee)
### Bug修复
diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java
index 72134cc1d..27dbf4728 100644
--- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java
@@ -20,12 +20,14 @@ import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.bean.copier.ValueProvider;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
+import cn.hutool.core.lang.Console;
import cn.hutool.core.lang.Editor;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.map.CaseInsensitiveMap;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ClassUtil;
+import cn.hutool.core.util.ModifierUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
@@ -42,15 +44,19 @@ import cn.hutool.core.util.StrUtil;
public class BeanUtil {
/**
- * 判断是否为Bean对象
- * 判定方法是是否存在只有一个参数的setXXX方法
+ * 判断是否为Bean对象,判定方法是:
+ *
+ *
+ * 1、是否存在只有一个参数的setXXX方法 + * 2、是否存在public类型的字段 + ** * @param clazz 待测试类 * @return 是否为Bean对象 * @see #hasSetter(Class) */ public static boolean isBean(Class> clazz) { - return hasSetter(clazz); + return hasSetter(clazz) || hasPublicField(clazz); } /** @@ -84,8 +90,7 @@ public class BeanUtil { */ public static boolean hasGetter(Class> clazz) { if (ClassUtil.isNormalClass(clazz)) { - final Method[] methods = clazz.getMethods(); - for (Method method : methods) { + for (Method method : clazz.getMethods()) { if (method.getParameterTypes().length == 0) { if (method.getName().startsWith("get") || method.getName().startsWith("is")) { return true; @@ -96,6 +101,25 @@ public class BeanUtil { return false; } + /** + * 指定类中是否有public类型字段(static字段除外) + * + * @param clazz 待测试类 + * @return 是否有public类型字段 + * @since 5.1.0 + */ + public static boolean hasPublicField(Class> clazz) { + if (ClassUtil.isNormalClass(clazz)) { + for (Field field : clazz.getFields()) { + if (ModifierUtil.isPublic(field) && false == ModifierUtil.isStatic(field)) { + //非static的public字段 + return true; + } + } + } + return false; + } + /** * 创建动态Bean * diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java index 3d477dbc8..ffc561205 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java @@ -1,14 +1,5 @@ package cn.hutool.core.bean.copier; -import java.io.Serializable; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; - import cn.hutool.core.bean.BeanDesc.PropDesc; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.provider.BeanValueProvider; @@ -20,10 +11,22 @@ import cn.hutool.core.lang.ParameterizedTypeImpl; import cn.hutool.core.lang.copier.Copier; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ModifierUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.TypeUtil; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; + /** * Bean拷贝 * @@ -214,12 +217,14 @@ public class BeanCopier
@@ -69,7 +69,7 @@ public class BeanConverterextends AbstractConverter { // 将Map动态代理为Bean return MapProxy.create((Map, ?>)value).toProxyBean(this.beanClass); } - + //限定被转换对象类型 return BeanCopier.create(value, ReflectUtil.newInstanceIfPossible(this.beanClass), this.beanType, this.copyOptions).copy(); } diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java index ec613194b..97ea9081c 100644 --- a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java @@ -3,7 +3,6 @@ package cn.hutool.core.bean; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.ValueProvider; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Console; import cn.hutool.core.map.MapUtil; import lombok.Getter; import lombok.Setter; @@ -101,6 +100,20 @@ public class BeanUtilTest { Assert.assertEquals(12, person.getAge()); } + /** + * 测试public类型的字段注入是否成功 + */ + @Test + public void mapToBeanTest2() { + HashMap map = CollUtil.newHashMap(); + map.put("name", "Joe"); + map.put("age", 12); + + Person2 person = BeanUtil.mapToBean(map, Person2.class, CopyOptions.create()); + Assert.assertEquals("Joe", person.name); + Assert.assertEquals(12, person.age); + } + @Test public void beanToMapTest() { SubPerson person = new SubPerson(); @@ -264,4 +277,10 @@ public class BeanUtilTest { private int age; private String openid; } + + public static class Person2 { + public String name; + public int age; + public String openid; + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToBeanTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToBeanTest.java index 65e3f725f..b9ed303d9 100644 --- a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToBeanTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToBeanTest.java @@ -80,4 +80,11 @@ public class ConvertToBeanTest { Assert.assertEquals("测试A11", subPerson.getName()); Assert.assertEquals("11213232", subPerson.getOpenid()); } + + @Test + public void nullStrToBeanTest(){ + String nullStr = "null"; + final SubPerson subPerson = Convert.convert(SubPerson.class, nullStr); + Assert.assertNull(subPerson); + } }