java可通过反射+introspector实现轻量级bean属性拷贝:遍历源对象getter获取属性名与值,匹配目标setter并调用赋值,支持基础类型自动转换及类型适配,忽略object继承方法。

Java 中可以通过反射机制手动实现一个轻量级的 Bean 属性拷贝工具,核心思路是:遍历源对象的 getter 方法,提取属性名和值;再在目标对象中查找对应 setter 方法,调用完成赋值。不依赖 Spring,但行为类似 BeanUtils.copyProperties。
获取源对象的可读属性(getter)
通过反射获取源类所有 public 的 getter 方法(方法名以 get 或 is 开头、无参数、返回值非 void),从中解析出属性名(如 getName() → name,isActive() → active)。
- 忽略
getClass、hashCode、toString等继承自 Object 的方法 - 使用
Introspector.getBeanInfo(clazz)可简化处理(自动跳过非业务属性) - 注意布尔类型优先匹配
isXxx(),再 fallback 到getXxx()
查找目标对象的可写属性(setter)
对每个解析出的属性名,构造标准 setter 方法名(如 name → setName),通过 Class.getDeclaredMethod("setName", Type.class) 查找。需注意:
- 参数类型要与 getter 返回值类型兼容(支持基础类型与包装类自动转换,如
int↔Integer) - 若目标类无对应 setter,跳过该属性(或抛异常,按需配置)
- 方法可能为 private,需调用
setAccessible(true)
执行属性赋值(支持简单类型转换)
获取源属性值后,不能直接传给 setter —— 需做类型适配。例如源是 Long,目标 setter 参数是 long,需调用 longValue();源是 String,目标是 LocalDateTime,则需额外注册转换器(简易版可先只支持基础类型+String+Date)。
- 基础类型(
int,boolean等)与其包装类之间自动拆/装箱 -
String到数字类型可用NumberUtils(Apache Commons)或Long.parseLong()等安全转换 - 日期类型建议统一用
java.time,字符串格式默认按yyyy-MM-dd HH:mm:ss解析(可扩展)
封装成工具方法(示例骨架)
以下是一个最小可行版本(无泛型擦除问题,不处理嵌套对象、集合、Map 等复杂结构):
public static void copyProperties(Object source, Object target) {
if (source == null || target == null) return;
try {
BeanInfo beanInfo = Introspector.getBeanInfo(source.getClass());
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : descriptors) {
if (pd.getReadMethod() == null || pd.getWriteMethod() == null) continue;
Object value = pd.getReadMethod().invoke(source);
if (value != null) {
// 类型兼容检查可在此增强
pd.getWriteMethod().invoke(target, value);
}
}
} catch (Exception e) {
throw new RuntimeException("Copy properties failed", e);
}
}
这个版本利用了 java.beans.Introspector,比纯 method 遍历更健壮,也自动跳过不可读/不可写属性,已覆盖大部分简单场景。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











