From 42b7815a4c686ac5e4a5a999a6b4b4544aeb67fe Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 14 Jul 2024 19:16:20 +0800 Subject: [PATCH] fix code --- .../hutool/core/bean/BeanDescFactory.java | 9 +++- .../hutool/core/bean/SimpleBeanDesc.java | 22 ++++++-- .../hutool/extra/aop/ProxyBeanTest.java | 54 +++++++++++++++++++ 3 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 hutool-extra/src/test/java/org/dromara/hutool/extra/aop/ProxyBeanTest.java diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/bean/BeanDescFactory.java b/hutool-core/src/main/java/org/dromara/hutool/core/bean/BeanDescFactory.java index ec0a7992f..7cbdb96d5 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/bean/BeanDescFactory.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/bean/BeanDescFactory.java @@ -52,7 +52,7 @@ public class BeanDescFactory { public static BeanDesc getBeanDescWithoutCache(final Class clazz) { if (RecordUtil.isRecord(clazz)) { return new RecordBeanDesc(clazz); - }else if(Proxy.isProxyClass(clazz) || ArrayUtil.isEmpty(FieldUtil.getFields(clazz))){ + } else if (isProxyClass(clazz) || ArrayUtil.isEmpty(FieldUtil.getFields(clazz))) { // 代理类和空字段的Bean不支持属性获取,直接使用方法方式 return new SimpleBeanDesc(clazz); } else { @@ -68,4 +68,11 @@ public class BeanDescFactory { public static void clearCache() { bdCache.clear(); } + + private static boolean isProxyClass(final Class clazz) { + // JDK代理类 + return Proxy.isProxyClass(clazz) || + // cglib代理类 + clazz.getName().contains("$$"); + } } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/bean/SimpleBeanDesc.java b/hutool-core/src/main/java/org/dromara/hutool/core/bean/SimpleBeanDesc.java index 92093e4bd..7eee77284 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/bean/SimpleBeanDesc.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/bean/SimpleBeanDesc.java @@ -15,12 +15,18 @@ package org.dromara.hutool.core.bean; import org.dromara.hutool.core.bean.path.AbstractBeanDesc; import org.dromara.hutool.core.reflect.method.MethodNameUtil; import org.dromara.hutool.core.reflect.method.MethodUtil; +import org.dromara.hutool.core.util.BooleanUtil; import java.lang.reflect.Method; import java.util.Map; /** - * 简单的Bean描述,只查找getter和setter方法 + * 简单的Bean描述,只查找getter和setter方法,规则如下: + * * * @author Looly * @since 6.0.0 @@ -75,9 +81,19 @@ public class SimpleBeanDesc extends AbstractBeanDesc { propMap.put(fieldName, propDesc); } else{ if(isSetter){ - propDesc.setter = method; + if(null == propDesc.setter || + propDesc.setter.getParameterTypes()[0].isAssignableFrom(method.getParameterTypes()[0])){ + // 如果存在多个重载的setter方法,选择参数类型最匹配的 + propDesc.setter = method; + } }else{ - propDesc.getter = method; + if(null == propDesc.getter || + (BooleanUtil.isBoolean(propDesc.getter.getReturnType()) && + BooleanUtil.isBoolean(method.getReturnType()) && + methodName.startsWith(MethodNameUtil.IS_PREFIX))){ + // 如果返回值为Boolean或boolean,isXXX优先于getXXX + propDesc.getter = method; + } } } } diff --git a/hutool-extra/src/test/java/org/dromara/hutool/extra/aop/ProxyBeanTest.java b/hutool-extra/src/test/java/org/dromara/hutool/extra/aop/ProxyBeanTest.java new file mode 100644 index 000000000..e9f2ece25 --- /dev/null +++ b/hutool-extra/src/test/java/org/dromara/hutool/extra/aop/ProxyBeanTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.extra.aop; + +import org.dromara.hutool.core.bean.BeanUtil; +import org.dromara.hutool.core.exception.HutoolException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +public class ProxyBeanTest { + + @Test + void proxyTest() { + final IBean bean = ProxyUtil.newProxyInstance((proxy, method, args) -> { + final String name = method.getName(); + switch (name){ + case "getName": + return "hutool"; + case "setName": + case "setAge": + return null; + case "getAge": + return 1; + } + throw new HutoolException("No method name: " + name); + }, IBean.class); + + // 测试代理类的Bean拷贝 + final Map map = BeanUtil.beanToMap(bean); + Assertions.assertEquals(2, map.size()); + Assertions.assertEquals("hutool", map.get("name")); + Assertions.assertEquals(1, map.get("age")); + } + + interface IBean{ + String getName(); + IBean setName(String name); + + int getAge(); + IBean setAge(int age); + } +}