xbo2018 commented on issue #69:
URL: https://github.com/apache/fesod/issues/69#issuecomment-3728134872
package org.springframework.cglib.beans;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.*;
/**
* 适配Spring CGLib 1.3版的NoCglibBeanMap
* 继承原BeanMap抽象类,无CGLib依赖,纯Java原生内省+反射实现
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class NoCglibBeanMap extends BeanMap {
// 缓存Bean的属性描述符(key:属性名,value:属性描述符)
private final Map<String, PropertyDescriptor> propertyDescriptorMap;
// 缓存Bean的属性名集合(不可变,符合原版本keySet固定的约定)
private final Set<String> keySet;
// Bean的Class类型(用于校验newInstance的Bean兼容性)
private final Class<?> beanClass;
// 属性过滤规则(REQUIRE_GETTER/REQUIRE_SETTER)
private final int require;
// ===================== 构造方法(适配原版本) =====================
/**
* 空构造(适配父类空构造)
*/
public NoCglibBeanMap() {
this.beanClass = null;
this.require = 0;
this.propertyDescriptorMap = Collections.emptyMap();
this.keySet = Collections.emptySet();
}
/**
* 带Bean的构造(核心构造,适配父类Bean构造)
* @param bean 目标Bean实例
*/
public NoCglibBeanMap(Object bean) {
this(bean, 0); // 默认不过滤属性(require=0)
}
/**
* 带Bean和require的构造(适配Generator的require配置)
* @param bean 目标Bean实例
* @param require 属性过滤规则(REQUIRE_GETTER/REQUIRE_SETTER)
*/
public NoCglibBeanMap(Object bean, int require) {
super(bean); // 调用父类构造,初始化bean成员变量
if (bean == null) {
throw new IllegalArgumentException("Class of bean unknown");
}
this.beanClass = bean.getClass();
this.require = require;
this.propertyDescriptorMap = new HashMap<>();
this.keySet = new LinkedHashSet<>();
// 初始化属性描述符和keySet
initPropertyDescriptors();
}
// ===================== 核心初始化逻辑 =====================
/**
* 初始化属性描述符:通过Java内省获取Bean的所有属性,按require过滤
*/
private void initPropertyDescriptors() {
try {
// 获取BeanInfo(排除Object类的属性,避免获取Object的toString/hashCode等方法)
BeanInfo beanInfo = Introspector.getBeanInfo(this.beanClass,
Object.class);
PropertyDescriptor[] descriptors =
beanInfo.getPropertyDescriptors();
// 遍历属性描述符,按require过滤
for (PropertyDescriptor pd : descriptors) {
String propName = pd.getName();
// 检查是否满足require过滤规则
if (isMeetRequire(pd)) {
propertyDescriptorMap.put(propName, pd);
keySet.add(propName);
}
}
} catch (IntrospectionException e) {
throw new RuntimeException("Failed to introspect bean class: " +
beanClass.getName(), e);
}
}
/**
* 检查属性是否满足require过滤规则
* @param pd 属性描述符
* @return true=满足规则,false=不满足(不加入keySet)
*/
private boolean isMeetRequire(PropertyDescriptor pd) {
// 无过滤规则,直接通过
if (require == 0) {
return true;
}
// 检查是否满足GETTER要求
boolean hasGetter = (require & REQUIRE_GETTER) == 0 ||
pd.getReadMethod() != null;
// 检查是否满足SETTER要求
boolean hasSetter = (require & REQUIRE_SETTER) == 0 ||
pd.getWriteMethod() != null;
return hasGetter && hasSetter;
}
// ===================== 实现父类抽象方法 =====================
/**
* 创建新的BeanMap实例,绑定新的Bean(适配原版本抽象方法)
*/
@Override
public BeanMap newInstance(Object bean) {
// 校验Bean类型兼容性(与当前BeanMap的beanClass一致)
if (bean != null &&
!this.beanClass.isAssignableFrom(bean.getClass())) {
throw new IllegalArgumentException("Bean class " +
bean.getClass().getName() + " is not compatible with " +
this.beanClass.getName());
}
return new NoCglibBeanMap(bean, this.require);
}
/**
* 获取指定属性的类型(适配原版本抽象方法)
*/
@Override
public Class getPropertyType(String name) {
if (name == null || !propertyDescriptorMap.containsKey(name)) {
return null;
}
return propertyDescriptorMap.get(name).getPropertyType();
}
/**
* 从指定Bean中获取指定key的属性值(核心抽象方法)
*/
@Override
public Object get(Object bean, Object key) {
// 基础参数校验
if (bean == null || key == null || !(key instanceof String)) {
return null;
}
String propName = (String) key;
PropertyDescriptor pd = propertyDescriptorMap.get(propName);
// 无该属性,返回null(符合原版本约定)
if (pd == null) {
return null;
}
// 获取getter方法,无getter返回null(符合原版本“写只读属性返回null”的约定)
Method getter = pd.getReadMethod();
if (getter == null) {
return null;
}
// 反射调用getter
try {
return getter.invoke(bean);
} catch (Exception e) {
throw new RuntimeException("Failed to get property [" + propName
+ "] from bean", e);
}
}
/**
* 给指定Bean设置指定key的属性值(核心抽象方法)
*/
@Override
public Object put(Object bean, Object key, Object value) {
// 基础参数校验
if (bean == null || key == null || !(key instanceof String)) {
return null;
}
String propName = (String) key;
PropertyDescriptor pd = propertyDescriptorMap.get(propName);
// 无该属性,返回null(符合原版本约定)
if (pd == null) {
return null;
}
// 获取setter方法,无setter忽略(符合原版本“设置只读属性被忽略”的约定)
Method setter = pd.getWriteMethod();
if (setter == null) {
return null;
}
// 获取旧值
Object oldValue = get(bean, key);
// 反射调用setter(处理参数类型适配)
try {
// 处理基本类型自动装箱(如int <-> Integer)
Object adaptedValue = adaptValueToPropertyType(value,
pd.getPropertyType());
setter.invoke(bean, adaptedValue);
return oldValue;
} catch (Exception e) {
throw new RuntimeException("Failed to set property [" + propName
+ "] to bean", e);
}
}
// ===================== 重写关键方法(优化性能/符合约定) =====================
/**
* 重写keySet方法:返回固定的属性名集合(不可变,符合原版本约定)
*/
@Override
public Set keySet() {
return Collections.unmodifiableSet(keySet);
}
// ===================== 辅助方法(类型适配) =====================
/**
* 适配值到属性类型(处理基本类型/包装类型转换)
*/
private Object adaptValueToPropertyType(Object value, Class<?>
propertyType) {
if (value == null) {
// 基本类型不允许null,抛出异常
if (propertyType.isPrimitive()) {
throw new IllegalArgumentException("Cannot set null to
primitive type [" + propertyType.getName() + "]");
}
return null;
}
// 类型匹配,直接返回
if (propertyType.isInstance(value)) {
return value;
}
// 处理基本类型与包装类型转换(如Integer -> int)
if (propertyType.isPrimitive()) {
if (propertyType == int.class && value instanceof Integer) {
return value;
} else if (propertyType == long.class && value instanceof Long) {
return value;
} else if (propertyType == boolean.class && value instanceof
Boolean) {
return value;
} else if (propertyType == double.class && value instanceof
Double) {
return value;
} else if (propertyType == float.class && value instanceof
Float) {
return value;
} else if (propertyType == short.class && value instanceof
Short) {
return value;
} else if (propertyType == byte.class && value instanceof Byte) {
return value;
} else if (propertyType == char.class && value instanceof
Character) {
return value;
} else {
throw new IllegalArgumentException("Cannot convert " +
value.getClass().getName() + " to primitive type " + propertyType.getName());
}
}
// 其他类型不支持转换,抛出异常
throw new IllegalArgumentException("Value type " +
value.getClass().getName() + " is not compatible with property type " +
propertyType.getName());
}
// ===================== 静态工厂方法(替代原create方法) =====================
/**
* 适配原版本的create静态方法,创建NoCglibBeanMap实例
*/
public static BeanMap create(Object bean) {
return new NoCglibBeanMap(bean);
}
/**
* 带require参数的工厂方法(适配原Generator的require配置)
*/
public static BeanMap create(Object bean, int require) {
return new NoCglibBeanMap(bean, require);
}
}
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]