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. hdu4085 Peach Blossom Spring

    Peach Blossom Spring http://acm.hdu.edu.cn/showproblem.php?pid=4085 Time Limit: 10000/5000 MS (Java/ ...

  2. 将资源文件夹中的文件通过流的方式写入到应用的File文件夹中

    //1.在Files文件夹中创建同名的数据库文件 File files = getFilesDir(); File file = new File(files, DBName); if(file.ex ...

  3. ShellCode的几种调用方法

    ShellCode是一种漏洞代码,中文名也叫填充数据,一般是用C语言或者汇编编写.在研究的过程中,自己也学到了一些东西,发现其中也有许多坑,所以贴出来,如果大家有碰到的,可以参考一下. 以启动电脑上的 ...

  4. nfs 文件共享 服务

    需要rpc服务: [root@xujiaxuan ftp]# service rpcbind start[root@xujiaxuan ftp]# chkconfig rpcbind on 设置开机自 ...

  5. FreeRADIUS + MySQL 安装配置笔记

    FreeRADIUS + MySQL 安装配置笔记 https://www.2cto.com/net/201110/106597.html

  6. 33.Search in Rotated Sorted Array---二分变形---《剑指offer》面试题8

    题目链接 题目大意:在一个旋转数组中,判断给定的target是否存在于该旋转数组中.数组中没有重复数值.例子如下: 法一:二分.确定中间元素之后,就要判断下一步是遍历左数组还是遍历右数组.如果左数组有 ...

  7. 解决TextView多行滑动与NestedScrollView等,滑动冲突,我的解决方案

    1.首先要明白,什么时候回TextView处理滑动,什么时候不处理滑动 1.1往上滑动,到达文本底部就不要再处理了,如果往上滑动不在底部则继续TextView滑动 1.2往下滑动,到达文本顶部就不要再 ...

  8. 12-4 NSString

    原文:http://rypress.com/tutorials/objective-c/data-types/nsstring NSString 在本教程的内容可能我们已经看到过很多次了,NSStri ...

  9. maven使用备忘

    maven的所有功能本质上都是通过插件来实现的所有的功能.archetype插件就是根据项目类型创建项目的插件.执行archetype:generate命令就会list一系列的项目类型,可以选择一个合 ...

  10. Leetcode 之Binary Tree Inorder Traversal(43)

    树的中序遍历.先不断压入左结点至末尾,再访问,再压入右结点.注意和先序遍历的比较 vector<int> inorderTraversal(TreeNode *root) { vector ...