This commit is contained in:
Looly 2024-07-14 19:16:20 +08:00
parent 4451cebe20
commit 42b7815a4c
3 changed files with 81 additions and 4 deletions

View File

@ -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("$$");
}
}

View File

@ -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方法规则如下
* <ul>
* <li>不匹配字段只查找getXXXisXXXsetXXX方法</li>
* <li>如果同时存在getXXX和isXXX返回值为Boolean或booleanisXXX优先</li>
* <li>如果同时存在setXXX的多个重载方法最小子类优先如setXXX(List)优先于setXXX(Collection)</li>
* </ul>
*
* @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或booleanisXXX优先于getXXX
propDesc.getter = method;
}
}
}
}

View File

@ -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<String, Object> 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);
}
}