Java反射—自己实现Bean的拷贝

       开发接口的过程中经常会遇到传出值的屏蔽问题,往往要删掉一些信息才能传给调用者,但是频繁的调用set不仅耗时而且容易错漏。

       这个时候会开始考虑用Apache BeanUtilsPropertyUtils,Spring BeanUtils,Cglib BeanCopier这些提供的工具类,但是有些项目里根本没有这些jar包就为了用这一个功能,还得自己添加。这种情况下还不如用反射自己手写一个。

       思路是新建一个对应的VO类,只写上接口需要的数据字段。为了减少遍历次数,最外层遍历VO的字段,里面遍历Model的字段,如果字段名一样表示需要拷贝,拷贝的时候根据需要转换数据类型。

	/**
	 * model转成可显示出去的类
	 * @param model
	 * @param vo
	 */
	public static void modelToVo(Object model, Object vo){
		Class clOne = model.getClass();
		Class clTwo = vo.getClass();
		Field[] fieldModel = clOne.getDeclaredFields();
		Field[] fieldVo = clTwo.getDeclaredFields();

		// 调用get方法
		for (int i = 0; i < fieldVo.length; i++){
			try{
				// model获取get
				Method getMethod = clOne.getDeclaredMethod("get" + captureName(fieldVo[i].getName()), new Class[]{});
				Object ob = getMethod.invoke(model, new Class[]{});
				if (null != ob){
					Class modelFieldClass = String.class;
					for (int j = 0; j < fieldModel.length; j++){
						if (fieldVo[i].getName().equals(fieldModel[j].getName())){
							modelFieldClass = fieldModel[j].getType();
							break;
						}
					}
					//处理日期格式
					if ("Timestamp".equals(modelFieldClass.getSimpleName())){
						Timestamp t = (Timestamp)ob;
						SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
						ob = sdf.format(t);
					}else if ("java.util.Date".equals(modelFieldClass.getName())){
						java.util.Date d = (java.util.Date)ob;
						SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
						ob = sdf.format(d);
					}else if ("java.sql.Date".equals(modelFieldClass.getName())){
						java.sql.Date d = (java.sql.Date)ob;
						Timestamp t = new Timestamp(d.getTime());
						SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
						ob = sdf.format(t);
					}

					// vo获取set
					Method setMethod = clTwo.getDeclaredMethod("set" + captureName(fieldVo[i].getName()), new Class[]{String.class});
					setMethod.invoke(vo, new Object[]{ob});
				}
			}catch (NoSuchMethodException e){
				e.printStackTrace();
			}catch (InvocationTargetException e){
				e.printStackTrace();
			}catch (IllegalAccessException e){
				e.printStackTrace();
			}

		}
	}
        //将首字母大写
	private static String captureName(String name) {
		char[] cs=name.toCharArray();
		cs[0]-=32;
		return String.valueOf(cs);

	}


}
最后,关于性能问题,暂无测试,但能应付一些简单的拷贝。

不频繁的调用这个方法还是能流畅的,如果频繁调用(比如10000次),就要加缓存了



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值