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. css 实现元素水平垂直居中总结5中方法

    个人总结,如有错误请指出,有好的建议请留言.o(^▽^)o 一.margin:0 auto:text-align:center:line-height方法 <div id="divAu ...

  2. 【POJ】1222 EXTENDED LIGHTS OUT(高斯消元)

    http://poj.org/problem?id=1222 竟然我理解了两天..... 首先先来了解异或方程组(或者说mod2方程组,modk的话貌似可以这样拓展出来) 对于一些我们需要求出的变量a ...

  3. python进行机器学习(二)之特征选择

    毫无疑问,解决一个问题最重要的是恰当选取特征.甚至创造特征的能力,这叫做特征选取和特征工程.对于特征选取工作,我个人认为分为两个方面: 1)利用python中已有的算法进行特征选取. 2)人为分析各个 ...

  4. 使用PTGui软件将全景图变成鱼眼图

    把全景图变成鱼眼图.方法一部分是自己研究的,一部分是参考学妹街景合成鱼眼照片的方法. 需要使用的软件是PTGui.是个收费软件,价格还不便宜.操作一下,安装完后就可以开始合成鱼眼图了. 加载图像 打开 ...

  5. 哈希表(一):解决hash冲突的几种方法

    (一)线性探测法 线性探测法是最简单的处理冲突的方法. (1)插入元素:插入元素时,如果发生冲突,算法将从该槽位向后遍历哈希表,直到找到表中的下一个空槽,并将该值放入到空槽当中. (2)查找元素:查找 ...

  6. AMD嵌入式G系列SoC协助优化Gizmo 2开发板

    http://www.gizmosphere.org/ AMD嵌入式G系列SoC协助优化Gizmo 2开发板 http://news.zol.com.cn/491/4910444.html

  7. python并发模块之concurrent.futures(二)

    python并发模块之concurrent.futures(二) 上次我们简单的了解下,模块的一些基本方法和用法,这里我们进一步对concurrent.futures做一个了解和拓展.上次的内容点这. ...

  8. python爬虫模块之URL管理器模块

    URL管理器模块 一般是用来维护爬取的url和未爬取的url已经新添加的url的,如果队列中已经存在了当前爬取的url了就不需要再重复爬取了,另外防止造成一个死循环.举个例子 我爬www.baidu. ...

  9. HDU 5118 GRE Words Once More!

    题目链接:HDU-5118 题意:给定一个有向无环图,每条边有一个权值.标定一些特定节点为“特殊节点”.从节点1出发到某“特殊节点”结束的路径,称为一个“GRE单词”.单词由路径上的权值组成.给定一组 ...

  10. ACdream 1157 Segments CDQ分治

    题目链接:https://vjudge.net/problem/ACdream-1157 题意: Problem Description 由3钟类型操作: 1)D L R(1 <= L < ...