package com.fpi.spring.qaepb.cps.util;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import com.fpi.spring.qaepb.cps.entity.po.Project;
import com.fpi.spring.qaepb.cps.entity.po.ProjectApproval; /**
* bean的属性拷贝工具类
*
* @date 2013-12-17
*
* @author yang_qiao
*
* @version 1.0
*/
public class BeanUtils { private static final Log logger = LogFactory.getLog(BeanUtils.class); /** bean嵌套 */
private static final String NESTED = "."; /**
* 复制bean的属性(支持嵌套属性,以点号分割)
*
* @param source
* 拷贝属性的源对象
*
* @param dest
* 拷贝属性的目的地对象
*
* @param includeProperties
* 拷贝的属性列表
*
* @author yang_qiao
*
* @throws InvocationTargetException
*
* @throws IllegalAccessException
*
* @throws IllegalArgumentException
*
* @throws InstantiationException
*
* @throws IntrospectionException
*
* @date 2013-12-18
*/
public static final void copyIncludeProperties(final Object source,
Object dest, final String[] includeProperties)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException, InstantiationException,
IntrospectionException {
if (includeProperties == null || includeProperties.length == 0) {
throw new IllegalArgumentException("未传入要拷贝的属性列表");
}
if (source == null) {
throw new IllegalArgumentException("要拷贝的源对象为空");
}
if (dest == null) {
throw new IllegalArgumentException("要拷贝的目的对象为空");
}
// 日志信息
if (logger.isTraceEnabled()) {
logger.trace("[source bean: " + source.getClass().getName() + " ]");
logger.trace("[destination bean: " + dest.getClass().getName()
+ " ]");
}
// 拷贝
for (String property : includeProperties) {
PropertyDescriptor sourcePropertyDescriptor = null;
PropertyDescriptor destPropertyDescriptor = null;
if (isSimpleProperty(property)) { // 简单属性
sourcePropertyDescriptor = getProperty(property, source);
destPropertyDescriptor = getProperty(property, dest);
if (sourcePropertyDescriptor == null) {
throw new IllegalArgumentException("要拷贝的源对象不存在该属性");
}
if (destPropertyDescriptor == null) {
throw new IllegalArgumentException("要拷贝到的目标对象不存在该属性");
}
copyProperty(property, source, dest);
} else { // 嵌套bean属性
Object target = dest;
Object realSource = source;
String[] nestedProperty = getNestedProperty(property);
if (nestedProperty != null && nestedProperty.length > 1) {
for (int i = 0; i < nestedProperty.length - 1; i++) {
sourcePropertyDescriptor = getProperty(
nestedProperty[i], realSource);
destPropertyDescriptor = getProperty(nestedProperty[i],
target);
if (sourcePropertyDescriptor == null) {
throw new IllegalArgumentException("要拷贝的源对象不存在该属性");
}
if (destPropertyDescriptor == null) {
throw new IllegalArgumentException(
"要拷贝到的目标对象不存在该属性");
}
Method readMethod = sourcePropertyDescriptor
.getReadMethod();
realSource = readMethod.invoke(realSource);
readMethod = destPropertyDescriptor.getReadMethod();
Method writeMethod = destPropertyDescriptor
.getWriteMethod();
Object value = readMethod.invoke(target);
if (value == null) {
value = destPropertyDescriptor.getPropertyType()
.newInstance();
writeMethod.invoke(target, value);
}
target = value;
}
final String prop = nestedProperty[nestedProperty.length - 1];
sourcePropertyDescriptor = getProperty(prop, realSource);
destPropertyDescriptor = getProperty(prop, target);
if (sourcePropertyDescriptor == null) {
throw new IllegalArgumentException("要拷贝的源对象不存在该属性");
}
if (destPropertyDescriptor == null) {
throw new IllegalArgumentException("要拷贝到的目标对象不存在该属性");
}
copyProperty(prop, realSource, target);
}
}
}
} /**
* 复制bean的属性(支持嵌套属性,以点号分割)
*
* @param source
* 拷贝属性的源对象
*
* @param dest
* 拷贝属性的目的地对象
*
* @param includeProperties
* 拷贝的属性列表
*
* @author yang_qiao
*
* @throws IntrospectionException
*
* @throws InvocationTargetException
*
* @throws IllegalAccessException
*
* @throws IllegalArgumentException
*
* @throws InstantiationException
*
* @throws ClassNotFoundException
*
* @throws IOException
*
* @date 2013-12-18
*/
public static void copyProperties(final Object source, final Object dest,
final String... excludeProperties) throws IntrospectionException,
IllegalArgumentException, IllegalAccessException,
InvocationTargetException, InstantiationException, IOException,
ClassNotFoundException {
final Object backupSource = clone(dest);
if (source == null) {
throw new IllegalArgumentException("要拷贝的源对象为空");
}
if (dest == null) {
throw new IllegalArgumentException("要拷贝的目的对象为空");
}
org.apache.commons.beanutils.BeanUtils.copyProperties(dest, source);
// 还原排除的属性值
revertProperties(backupSource, dest, excludeProperties);
} /**
* 从备份对象中还原属性
*
* @param backup
* 备份bean
*
* @param target
* 目标bean
*
* @param properties
* 属性列表
*
* @author yang_qiao
*
* @throws InvocationTargetException
*
* @throws IllegalAccessException
*
* @throws IllegalArgumentException
*
* @throws IntrospectionException
*
* @throws InstantiationException
*
* @date 2013-12-18
*/
private static void revertProperties(final Object backup, Object target,
final String... properties) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException,
IntrospectionException, InstantiationException {
if (properties == null || properties.length == 0) {
return;
}
if (backup == null) {
throw new IllegalArgumentException("备份对象为空");
}
if (target == null) {
throw new IllegalArgumentException("目的对象为空");
}
// 日志信息
if (logger.isTraceEnabled()) {
logger.trace("[source bean: " + backup.getClass().getName() + " ]");
logger.trace("[destination bean: " + target.getClass().getName()
+ " ]");
}
// 拷贝
for (String property : properties) {
PropertyDescriptor sourcePropertyDescriptor = null;
PropertyDescriptor destPropertyDescriptor = null;
if (isSimpleProperty(property)) { // 简单属性
sourcePropertyDescriptor = getProperty(property, backup);
destPropertyDescriptor = getProperty(property, target);
if (sourcePropertyDescriptor == null) {
throw new IllegalArgumentException("要拷贝的源对象不存在该属性");
}
if (destPropertyDescriptor == null) {
throw new IllegalArgumentException("要拷贝到的目标对象不存在该属性");
}
copyProperty(property, backup, target);
} else { // 嵌套bean属性
Object targetObj = target;
Object realBackup = backup;
String[] nestedProperty = getNestedProperty(property);
if (nestedProperty != null && nestedProperty.length > 1) {
for (int i = 0; i < nestedProperty.length - 1; i++) {
sourcePropertyDescriptor = getProperty(
nestedProperty[i], realBackup);
destPropertyDescriptor = getProperty(nestedProperty[i],
targetObj);
if (sourcePropertyDescriptor == null) {
throw new IllegalArgumentException("要拷贝的源对象不存在该属性");
}
if (destPropertyDescriptor == null) {
throw new IllegalArgumentException(
"要拷贝到的目标对象不存在该属性");
}
Method readMethod = sourcePropertyDescriptor
.getReadMethod();
realBackup = readMethod.invoke(realBackup);
if (realBackup == null) { // 判断备份对象嵌套属性是否为空
realBackup = sourcePropertyDescriptor
.getPropertyType().newInstance();
}
Method writeMethod = destPropertyDescriptor
.getWriteMethod();
readMethod = destPropertyDescriptor.getReadMethod();
Object value = readMethod.invoke(targetObj);
if (value == null) {
value = destPropertyDescriptor.getPropertyType()
.newInstance();
writeMethod.invoke(targetObj, value);
}
targetObj = value;
}
final String prop = nestedProperty[nestedProperty.length - 1];
sourcePropertyDescriptor = getProperty(prop, realBackup);
destPropertyDescriptor = getProperty(prop, targetObj);
if (sourcePropertyDescriptor == null) {
throw new IllegalArgumentException("要拷贝的源对象不存在该属性");
}
if (destPropertyDescriptor == null) {
throw new IllegalArgumentException("要拷贝到的目标对象不存在该属性");
}
copyProperty(prop, realBackup, targetObj);
}
}
}
} /**
* 对象克隆
*
* @author yang_qiao
*
* @date 2013-12-18
*/
private static Object clone(final Object value) throws IOException,
ClassNotFoundException {
// 字节数组输出流,暂存到内存中
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// 序列化
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(value);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
// 反序列化
return ois.readObject();
} /**
* 判断是否为简单属性,是,返回ture
*
* @author yang_qiao
*
* @date 2013-12-18
*/
private static boolean isSimpleProperty(final String property) {
return !property.contains(NESTED);
} /**
* 获取目标bean的属性
*
* @author yang_qiao
*
* @date 2013-12-17
*/
private static PropertyDescriptor getProperty(final String propertyName,
final Object target) {
if (target == null) {
new IllegalArgumentException("查询属性的对象为空");
}
if (propertyName == null || "".equals(propertyName)) {
new IllegalArgumentException("查询属性不能为空值");
}
PropertyDescriptor propertyDescriptor = null;
try {
propertyDescriptor = new PropertyDescriptor(propertyName,
target.getClass());
} catch (IntrospectionException e) {
logger.info("不存在该属性");
return null;
}
return propertyDescriptor;
} /**
* 单个属性复制--原数据源和目的数据源必须要有该属性方可
*
* @author yang_qiao
*
* @throws InvocationTargetException
*
* @throws IllegalAccessException
*
* @throws IllegalArgumentException
*
* @throws IntrospectionException
*
* @date 2013-12-17
*/
public static void copyProperty(final String propertyName,
final Object source, Object dest) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException,
IntrospectionException {
PropertyDescriptor property;
property = new PropertyDescriptor(propertyName, source.getClass());
Method getMethod = property.getReadMethod();
Object value = getMethod.invoke(source);
property = new PropertyDescriptor(propertyName, dest.getClass());
Method setMethod = property.getWriteMethod();
setMethod.invoke(dest, value);
} /**
* 获取嵌套Bean的属性
*
* @author yang_qiao
*
* @date 2013-12-18
*/
public static String[] getNestedProperty(final String nestedProperty) {
if (nestedProperty == null || "".equals(nestedProperty)) {
new IllegalArgumentException("参数为空值");
}
return nestedProperty.split("\\" + NESTED);
} public static void main(String[] args) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException,
InstantiationException, IntrospectionException, IOException,
ClassNotFoundException {
Project oldProject = new Project();
Project newProject = new Project();
ProjectApproval projectApproval = new ProjectApproval();
projectApproval.setFirstCheckComment("jsoncheck");
projectApproval.setExplorationComment("shitCheck");
oldProject.setProjectApproval(projectApproval);
oldProject.setBuildAddress("json");
oldProject.setContact("json");
final String[] includeProperties = new String[] { "contact",
"projectApproval.firstCheckComment",
"projectApproval.explorationComment" };
BeanUtils.copyIncludeProperties(oldProject, newProject,
includeProperties);
System.out.println(newProject.getContact());
System.out.println(newProject.getProjectApproval()
.getFirstCheckComment());
System.out.println(newProject.getProjectApproval()
.getExplorationComment());
System.out.println(newProject.getApprovalStatus());
System.out.println(newProject.getBuildAddress()); System.out.println("================================"); oldProject = new Project();
newProject = new Project();
projectApproval = new ProjectApproval();
projectApproval.setFirstCheckComment("jsoncheck_");
projectApproval.setExplorationComment("shitCheck_");
oldProject.setProjectApproval(projectApproval);
oldProject.setBuildAddress("json_");
oldProject.setContact("json_");
final String[] excludeProperties = null;
BeanUtils.copyProperties(oldProject, newProject, excludeProperties);
System.out.println(newProject.getContact());
System.out.println(newProject.getProjectApproval()
.getExplorationComment());
System.out.println(newProject.getProjectApproval()
.getFirstCheckComment());
System.out.println(newProject.getApprovalStatus());
System.out.println(newProject.getBuildAddress()); } }

一个Bean属性拷贝的工具类的更多相关文章

  1. 基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil

    基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil,把日常能用到的各种CRUD都进行了简化封装,让普通程序员只需关注业务即可,因为非常简单,故直接贴源代码,大家若需使用可以直 ...

  2. 实现一个简单的http请求工具类

    OC自带的http请求用起来不直观,asihttprequest库又太大了,依赖也多,下面实现一个简单的http请求工具类 四个文件源码大致如下,还有优化空间 MYHttpRequest.h(类定义, ...

  3. java bean属性拷贝工具类比对(性能+功能)

    业务系统中经常需要两个对象进行属性的拷贝,不能否认逐个的对象拷贝是最快速最安全的做法,但是当数据对象的属性字段数量超过程序员的容忍的程度比如通常超过5个属性的时候,代码因此变得臃肿不堪,使用一些方便的 ...

  4. Spring的Bean,AOP以及工具类初探

    1.Bean(Ioc) BeanWrapper 根据JavaDoc中的说明,BeanWrapper提供了设置和获取属性值(单个的或者是批量的),获取属性描述信息.查询只读或者可写属性等功能.不仅如此, ...

  5. 分享一个关于jackson的Json工具类

    直接贴代码: import org.codehaus.jackson.map.DeserializationConfig.Feature; import org.codehaus.jackson.ma ...

  6. Java操作属性文件之工具类

    最近空闲时间整理一下平时常用的一下工具类,重复造轮子实在是浪费时间,如果不正确或者有待改善的地方,欢迎指教... package com.hsuchan.business.utils; import ...

  7. 一个简单IP防刷工具类, x秒内最多允许y次单ip操作

    IP防刷,也就是在短时间内有大量相同ip的请求,可能是恶意的,也可能是超出业务范围的.总之,我们需要杜绝短时间内大量请求的问题,怎么处理? 其实这个问题,真的是太常见和太简单了,但是真正来做的时候,可 ...

  8. 一个好的Java时间工具类DateTime

    此类的灵感来源于C# 虽然网上有什么date4j,但是jar太纠结了,先给出源码,可以继承到自己的util包中,作为一个资深程序员,我相信都有不少好的util工具类,我也希望经过此次分享,能带动技术大 ...

  9. 自己动手写一个U盘拷贝小工具

    这是五一期间,参照知乎上一篇的文章<十行代码--用python写一个USB病毒>写成的,最初只是单纯的想写成死循环,直到文件占满硬盘为止,第一个遇到的问题是,拷贝到硬盘之后,由于要无限次拷 ...

随机推荐

  1. hdu 4903 The only survival

    The only survival http://acm.hdu.edu.cn/showproblem.php?pid=4903 Time Limit: 40000/20000 MS (Java/Ot ...

  2. 51Nod 1095 Anigram单词 | Hash

    Input示例 5 add dad bad cad did 3 add cac dda Output示例 1 0 2 题意:一系列字符串,查询字符串S,能通过其他字符串交换串内字符顺序得到的字符串个数 ...

  3. 51Nod 1087 1 10 100 1000 | 数学

    Input示例 3 1 2 3 Output示例 1 1 0 #include "bits/stdc++.h" using namespace std; #define LL lo ...

  4. SPOJ AMR11E Distinct Primes 基础数论

    Arithmancy is Draco Malfoy's favorite subject, but what spoils it for him is that Hermione Granger i ...

  5. \(\rm LightOJ 1371 - Energetic Pandas 简单计数+组合\)

    http://www.lightoj.com/volume_showproblem.php?problem=1371 题意:给你n根竹子,和n只熊猫(XD),每个熊猫只能选择重量不大于它的竹子,问有几 ...

  6. LightOJ 1226 - One Unit Machine Lucas/组合数取模

    题意:按要求完成n个任务,每个任务必须进行a[i]次才算完成,且按要求,第i个任务必须在大于i任务完成之前完成,问有多少种完成顺序的组合.(n<=1000 a[i] <= 1e6 mod ...

  7. 【C++对象模型】第二章 构造函数语意学

    1.Default Constructor 当编译器需要的时候,default constructor会被合成出来,只执行编译器所需要的任务(将members适当初始化). 1.1  带有 Defau ...

  8. Linux系统开机启动时的工作原理

    Linux系统开机启动时的工作原理也是深入了解Linux系统核心工作原理的一个很好的途径. 启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至 ...

  9. 【HDU】2222 Keywords Search

    [算法]AC自动机 [题解]本题注意题意是多少关键字能匹配而不是能匹配多少次,以及可能有重复单词. 询问时AC自动机与KMP最大的区别是因为建立了trie,所以对于目标串T与自动机串是否匹配只需要直接 ...

  10. 人人都能掌握的Java服务端性能优化方案

    作为一个Java后端开发,我们写出的大部分代码都决定着用户的使用体验.如果我们的后端代码性能不好,那么用户在访问我们的网站时就要浪费一些时间等待服务器的响应.这就可能导致用户投诉甚至用户的流失. 关于 ...