我有一个简单的 Java POJO,我会将属性复制到同一个 POJO 类的另一个实例。
我知道我可以用 BeanUtils.copyProperties() 做到这一点,但我想避免使用第三方库。
那么,如何简单、正确、安全地做到这一点呢?
顺便说一句,我使用的是 Java 6。
我想如果您查看 BeanUtils 的源代码,它将向您展示如何在不实际使用 BeanUtils 的情况下执行此操作。
如果您只是想创建 POJO 的副本(与将属性从一个 POJO 复制到另一个不同),您可以更改源 bean 以实现 clone() 方法和 Cloneable 接口。
在为 Google App Engine 开发应用程序时,我遇到了同样的问题,由于公共日志记录限制,我无法使用 BeanUtils。无论如何,我想出了这个解决方案并且对我来说工作得很好。
public static void copyProperties(Object fromObj, Object toObj) {
Class<? extends Object> fromClass = fromObj.getClass();
Class<? extends Object> toClass = toObj.getClass();
try {
BeanInfo fromBean = Introspector.getBeanInfo(fromClass);
BeanInfo toBean = Introspector.getBeanInfo(toClass);
PropertyDescriptor[] toPd = toBean.getPropertyDescriptors();
List<PropertyDescriptor> fromPd = Arrays.asList(fromBean
.getPropertyDescriptors());
for (PropertyDescriptor propertyDescriptor : toPd) {
propertyDescriptor.getDisplayName();
PropertyDescriptor pd = fromPd.get(fromPd
.indexOf(propertyDescriptor));
if (pd.getDisplayName().equals(
propertyDescriptor.getDisplayName())
&& !pd.getDisplayName().equals("class")) {
if(propertyDescriptor.getWriteMethod() != null)
propertyDescriptor.getWriteMethod().invoke(toObj, pd.getReadMethod().invoke(fromObj, null));
}
}
} catch (IntrospectionException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
任何改进或建议都非常受欢迎。
另一种选择是MapStruct,它在构建时生成映射代码,从而产生在运行时不需要任何依赖项的类型安全映射(免责声明:我是 MapStruct 的作者)。
嘿,朋友们只需使用我创建的 ReflectionUtil 类将一个 bean 值复制到另一个类似的 bean。此类还将复制 Collections 对象。https://github.com/vijayshegokar/Java/blob/master/Utility/src/common/util/reflection/ReflectionUtil.java
注意:此 bean 必须具有与类型相似的变量名称,并且具有用于它们的 getter 和 setter。
现在添加了更多功能。您还可以将一个实体数据复制到其 bean。如果一个实体中有另一个实体,那么您可以将内部实体的运行时更改的映射选项传递给它的相关 bean。
例如。
ParentEntity parentEntityObject = getParentDataFromDB();
Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>();
map.put(InnerBean1.class, InnerEntity1.class);
map.put(InnerBean2.class, InnerEntity2.class);
ParentBean parent = ReflectionUtil.copy(ParentBean.class, parentEntityObject, map);
当您的实体包含关系时,这种情况非常有用。
查看JavaBeans API,尤其是Introspector类。您可以使用 BeanInfo 元数据来获取和设置属性。如果您还没有阅读JavaBeans 规范,最好阅读一下。熟悉反射 API也很有帮助。
没有简单的方法可以做到这一点。Introspector 和 Java bean 库是一体的 - BeanUtils 是一个简单的包装器,并且运行良好。没有库只是为了没有库一般来说是个坏主意——这是有原因的,从一开始就是公共的——Java应该存在的公共功能,但没有。
我遇到了一些Introspector.getBeanInfo
没有返回所有属性的问题,所以我最终实现了字段副本而不是属性副本。
public static <T> void copyFields(T target, T source) throws Exception{
Class<?> clazz = source.getClass();
for (Field field : clazz.getFields()) {
Object value = field.get(source);
field.set(target, value);
}
}
您可以使用Java Reflection API来实现它。
public static <T> void copy(T target, T source) throws Exception {
Class<?> clazz = source.getClass();
for (Field field : clazz.getDeclaredFields()) {
if (Modifier.isPrivate(field.getModifiers()))
field.setAccessible(true);
Object value = field.get(source);
field.set(target, value);
}
}