Looly 5 年 前
コミット
15b6bb7aef

+ 2 - 0
CHANGELOG.md

@@ -6,6 +6,8 @@
 ## 5.2.5
 
 ### 新特性
+* 【core   】     增加逻辑,对于原始类型注入,(issue#797@Github)
+
 ### Bug修复
 
 -------------------------------------------------------------------------------------------------------------

+ 1 - 1
bin/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-exec mvn clean source:jar javadoc:javadoc install -Dmaven.test.skip=false -Dmaven.javadoc.skip=false
+exec mvn -T 1C clean source:jar javadoc:javadoc install -Dmaven.test.skip=false -Dmaven.javadoc.skip=false

+ 2 - 3
hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java

@@ -11,7 +11,6 @@ import java.lang.annotation.Inherited;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
-import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Method;
 import java.util.HashMap;
@@ -67,7 +66,7 @@ public class AnnotationUtil {
 	 * 如果无指定的属性方法返回null
 	 *
 	 * @param <T>            注解值类型
-	 * @param annotationEle  {@link AccessibleObject},可以是Class、Method、Field、Constructor、ReflectPermission
+	 * @param annotationEle  {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
 	 * @param annotationType 注解类型
 	 * @return 注解对象
 	 * @throws UtilException 调用注解中的方法时执行异常
@@ -81,7 +80,7 @@ public class AnnotationUtil {
 	 * 如果无指定的属性方法返回null
 	 *
 	 * @param <T>            注解值类型
-	 * @param annotationEle  {@link AccessibleObject},可以是Class、Method、Field、Constructor、ReflectPermission
+	 * @param annotationEle  {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
 	 * @param annotationType 注解类型
 	 * @param propertyName   属性名,例如注解中定义了name()方法,则 此处传入name
 	 * @return 注解对象

+ 1 - 1
hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java

@@ -283,7 +283,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
 					ReflectUtil.setFieldValue(bean, field, value);
 				} else{
 					// 执行set方法注入值
-					setterMethod.invoke(bean, value);
+					ReflectUtil.invoke(bean, setterMethod, value);
 				}
 			} catch (Exception e) {
 				if (false ==copyOptions.ignoreError) {

+ 39 - 3
hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java

@@ -304,7 +304,7 @@ public class ReflectUtil {
 		Assert.notNull(obj);
 		Assert.notBlank(fieldName);
 
-		final Field field = getField((obj instanceof Class) ? (Class<?>)obj : obj.getClass(), fieldName);
+		final Field field = getField((obj instanceof Class) ? (Class<?>) obj : obj.getClass(), fieldName);
 		Assert.notNull(field, "Field [{}] is not exist in [{}]", fieldName, obj.getClass().getName());
 		setFieldValue(obj, field, value);
 	}
@@ -320,8 +320,8 @@ public class ReflectUtil {
 	public static void setFieldValue(Object obj, Field field, Object value) throws UtilException {
 		Assert.notNull(field, "Field in [{}] not exist !", obj);
 
+		final Class<?> fieldType = field.getType();
 		if (null != value) {
-			Class<?> fieldType = field.getType();
 			if (false == fieldType.isAssignableFrom(value.getClass())) {
 				//对于类型不同的字段,尝试转换,转换失败则使用原对象类型
 				final Object targetValue = Convert.convert(fieldType, value);
@@ -329,6 +329,9 @@ public class ReflectUtil {
 					value = targetValue;
 				}
 			}
+		} else {
+			// 获取null对应默认值,防止原始类型造成空指针问题
+			value = ClassUtil.getDefaultValue(fieldType);
 		}
 
 		setAccessible(field);
@@ -848,6 +851,15 @@ public class ReflectUtil {
 	/**
 	 * 执行方法
 	 *
+	 * <p>
+	 * 对于用户传入参数会做必要检查,包括:
+	 *
+	 * <pre>
+	 *     1、忽略多余的参数
+	 *     2、参数不够补齐默认值
+	 *     3、传入参数为null,但是目标参数类型为原始类型,做转换
+	 * </pre>
+	 *
 	 * @param <T>    返回对象类型
 	 * @param obj    对象,如果执行静态方法,此值为<code>null</code>
 	 * @param method 方法(对象方法或static方法都可)
@@ -859,8 +871,32 @@ public class ReflectUtil {
 	public static <T> T invoke(Object obj, Method method, Object... args) throws UtilException {
 		setAccessible(method);
 
+		// 检查用户传入参数:
+		// 1、忽略多余的参数
+		// 2、参数不够补齐默认值
+		// 3、传入参数为null,但是目标参数类型为原始类型,做转换
+		// 4、传入参数类型不对应,尝试转换类型
+		final Class<?>[] parameterTypes = method.getParameterTypes();
+		final Object[] actualArgs = new Object[parameterTypes.length];
+		if (null != args) {
+			for (int i = 0; i < actualArgs.length; i++) {
+				if (i >= args.length || null == args[i]) {
+					// 越界或者空值
+					actualArgs[i] = ClassUtil.getDefaultValue(parameterTypes[i]);
+				} else if (false == parameterTypes[i].isAssignableFrom(args[i].getClass())) {
+					//对于类型不同的字段,尝试转换,转换失败则使用原对象类型
+					final Object targetValue = Convert.convert(parameterTypes[i], args[i]);
+					if (null != targetValue) {
+						actualArgs[i] = targetValue;
+					}
+				} else {
+					actualArgs[i] = args[i];
+				}
+			}
+		}
+
 		try {
-			return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, args);
+			return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, actualArgs);
 		} catch (Exception e) {
 			throw new UtilException(e);
 		}

+ 2 - 2
hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java

@@ -321,9 +321,9 @@ public class BeanUtilTest {
 
 	@Test
 	public void beanToBeanTest(){
-		// 复对象无getter方法导致报错的问题
+		// 复对象无getter方法导致报错的问题
 		Page page1=new Page();
-		BeanUtil.toBean(page1, Page.class, CopyOptions.create().setIgnoreNullValue(true));
+		BeanUtil.toBean(page1, Page.class);
 	}
 
 	public static class Page {