This commit is contained in:
Looly
2023-04-23 00:05:39 +08:00
parent 20636feb85
commit f226b8418a
11 changed files with 103 additions and 66 deletions

View File

@@ -83,7 +83,8 @@ public class AnnotationProxy<T extends Annotation> implements Annotation, Invoca
* @return 属性(方法结果)映射
*/
private Map<String, Object> initAttributes() {
final Method[] methods = MethodUtil.getMethods(this.type);
// 只缓存注解定义的方法
final Method[] methods = MethodUtil.getDeclaredMethods(this.type);
final Map<String, Object> attributes = new HashMap<>(methods.length, 1);
for (final Method method : methods) {

View File

@@ -324,7 +324,8 @@ public class AnnotationUtil {
}
/**
* 设置新的注解的属性(字段)值
* 设置新的注解的属性(字段)值<br>
* 注意此方法在jdk9+中抛出异常,须添加`--add-opens=java.base/java.lang=ALL-UNNAMED`启动参数
*
* @param annotation 注解对象
* @param annotationField 注解属性(字段)名称

View File

@@ -37,6 +37,24 @@ import java.lang.reflect.*;
*/
public class ReflectUtil {
/**
* 设置方法为可访问(私有方法可以被外部调用),静默调用,抛出异常则跳过<br>
* 注意此方法在jdk9+中抛出异常,须添加`--add-opens=java.base/java.lang=ALL-UNNAMED`启动参数
*
* @param <T> AccessibleObject的子类比如Class、Method、Field等
* @param accessibleObject 可设置访问权限的对象比如Class、Method、Field等
* @return 被设置可访问的对象
* @throws SecurityException 访问被禁止抛出此异常
*/
public static <T extends AccessibleObject> T setAccessibleQuietly(final T accessibleObject) {
try{
setAccessible(accessibleObject);
} catch (final RuntimeException ignore){
// ignore
}
return accessibleObject;
}
/**
* 设置方法为可访问(私有方法可以被外部调用)<br>
* 注意此方法在jdk9+中抛出异常,须添加`--add-opens=java.base/java.lang=ALL-UNNAMED`启动参数
@@ -50,7 +68,6 @@ public class ReflectUtil {
public static <T extends AccessibleObject> T setAccessible(final T accessibleObject) throws SecurityException {
if (null != accessibleObject && !accessibleObject.isAccessible()) {
accessibleObject.setAccessible(true);
return accessibleObject;
}
return accessibleObject;
}

View File

@@ -361,15 +361,26 @@ public class ObjUtil {
* @see #cloneByStream(Object)
*/
public static <T> T clone(final T obj) {
T result = ArrayUtil.clone(obj);
if (null == result) {
if (obj instanceof Cloneable) {
result = MethodUtil.invoke(obj, "clone");
} else {
result = cloneByStream(obj);
final T result = ArrayUtil.clone(obj);
if(null != result){
// 数组
return result;
}
if (obj instanceof Cloneable) {
try{
return MethodUtil.invoke(obj, "clone");
} catch (final HutoolException e){
if(e.getCause() instanceof IllegalAccessException){
// JDK9+下可能无权限
return cloneByStream(obj);
}else {
throw e;
}
}
}
return result;
return cloneByStream(obj);
}
/**

View File

@@ -5,6 +5,8 @@ import org.dromara.hutool.core.util.ObjUtil;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import java.lang.annotation.*;
import java.lang.reflect.Method;
@@ -113,7 +115,9 @@ public class AnnotationUtilTest {
}
@Test
@EnabledForJreRange(max = JRE.JAVA_8)
public void testSetValue() {
// jdk9+中抛出异常,须添加`--add-opens=java.base/java.lang=ALL-UNNAMED`启动参数
final AnnotationForTest annotation = ClassForTest.class.getAnnotation(AnnotationForTest.class);
final String newValue = "is a new value";
Assertions.assertNotEquals(newValue, annotation.value());
@@ -124,6 +128,7 @@ public class AnnotationUtilTest {
@Test
public void testGetAnnotationAlias() {
final MetaAnnotationForTest annotation = AnnotationUtil.getAnnotationAlias(AnnotationForTest.class, MetaAnnotationForTest.class);
Assertions.assertNotNull(annotation);
Assertions.assertEquals(annotation.value(), annotation.alias());
Assertions.assertEquals(MetaAnnotationForTest.class, annotation.annotationType());
}

View File

@@ -20,6 +20,8 @@ import org.dromara.hutool.core.lang.tuple.Tuple;
import org.dromara.hutool.core.reflect.MethodUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import java.io.Serializable;
import java.lang.reflect.Method;
@@ -181,17 +183,16 @@ public class LambdaUtilTest {
final BiConsumer<Bean, Long> setId = LambdaUtil.buildSetter(MethodUtil.getMethod(Bean.class, "setId", Long.class));
final BiConsumer<Bean, Long> setId2 = LambdaUtil.buildSetter(Bean.class, Bean.Fields.id);
final BiConsumer<Bean, Boolean> setFlag = LambdaUtil.buildSetter(Bean.class, Bean.Fields.flag);
Assertions.assertEquals(setId, setId2);
setId.accept(bean, 3L);
setFlag.accept(bean, true);
Assertions.assertEquals(3L, (long) bean.getId());
Assertions.assertTrue(bean.isFlag());
}
@Test
void buildSetterTest() {
@EnabledForJreRange(max = JRE.JAVA_8)
void buildSetterWithPrimitiveTest() {
// 原始类型参数在jdk9+中构建setter异常
final Bean bean = new Bean();
bean.setId(2L);
bean.setFlag(false);
@@ -339,7 +340,7 @@ public class LambdaUtilTest {
@Test
void getInvokeMethodErrorTest() {
// 非函数接口返回异常
Assertions.assertThrows(IllegalArgumentException.class, ()->{
Assertions.assertThrows(IllegalArgumentException.class, () -> {
LambdaUtil.getInvokeMethod(LambdaUtilTest.class);
});
}