基于BeanUtils和Annotation的值copy工具类(转载)

本文探讨了如何改进常见的Java代码片段,减少冗余的getter/setter调用。作者提出,虽然BeanUtils的populate方法可以简化部分操作,但其要求Map类型的源对象,且不适应不同命名习惯。因此,文章建议扩展BeanUtils以适应更多的场景,包括从ResultSet、请求参数到Java Bean的值复制,并强调了这种值复制在各种场景中的普遍性。
摘要由CSDN通过智能技术生成
 

关键字
Javabean, beanutils, annotation, introspection, SQL, ORM

 

一,一些可改进的代码片段
据我平常观察,周围的同事还存在不少类似的代码,举两例进行说明:
这段是操作ResultSet的

  1. CustBean bean = new CustBean();
  2. bean.setCustId(rs.getString("CUST_ID"))
  3. bean.setCustName(rs.getString("CUST_NAME"))
  4. ....
  5. // more similar code
  6. ...

这段是Servlet或其它业务类中的

  1. CustBean bean = new CustBean();
  2. bean.setCustId(request.getParameter("CUST_ID"))
  3. bean.setCustName(request.getParameter("CUST_NAME"))
  4. ....

依次类推,类似的getter/setter随处可见,以至代码相当冗余,还白白耗费键盘功夫.
当然,以上的代码如果在hibernate或其它ORM框架的支撑下,是不会出现的.
所以,你如果从一开始就掉在这些框架温柔的陷井里,也许还会难以理解这种写法的存在.

拿第二段来说,如果页面传入参数的名称和Bean中的property一致的话,其实就可以用commons beanutils工具包来简化:

  1. BeanUtils.populate(bean, request.getParameterMap())

那更进一步,如果常用对象都能用值copy的方式送入到指定bean中,代码量将大大减少;

可遗憾的是,BeanUtils.populate()方法,源对象参数只能是Map类型,
况且,对于数据库表字段或者页面参数命名,有人喜欢大写加个下划线,有人喜欢小写加个下划线,而我个人则喜欢直接用Java类命名方式:首字母大写来搞定.
所以,想要进行省事的值copy运算,得对beanutils进行扩展,以适应不同的场景,必竟人的习惯是一样很可怕的东西,相当顽固,一旦养成,很难改变.

其实,在Java中从某种内部对象向bean进行的值copy场景,出现的机率是相当高的.除非你完全摒弃MVC的精神,另搞一套新鲜玩法.
还有些场景,我们得从外部XML直接装载数据到bean,这些都算是一种值copy的应用,基本可以说无处不在!

二,回头再从beanutils说起
如果曾用过apache commons的这个工具包,都会留意到它的这两个实用功能:

  • BeanUtils.populate(dest, src)

    此方法可以将src对象中的属性值,逐一对应地填充到做为dest参数的JavaBean中,
    但有两点限制:
    1,,src对象一定是Map类型;就像前面的例子中提到的一样
    2,,src对象中的key值,一定是和JavaBean提供的setter方法保持统一的命名规范,因为populate的内部实现本身就是基于introspection的.

  • BeanUtils.copyProperties(dest, src)

    这个就更直接了.dest和src都是JavaBean,但两者所属类型可以不一样,只要property的setter能对应起来,就能够完成值copy.
    在本文的工具案例中,对于copyProperties是不需要的,已经给了替代统一的实现方案.

    很显然,以上两个方法都是挺实用的.在不少我们已接触的开源框架中都有用到beanutils,Struts的ActionForm值自动填充就是一例.
    但在我个人实用应用中,它们都表现很大的局限性,仍然不够灵活.
    最为突出的不便之处在于,beanutils对于src参数对象的要求太过于苛刻了:
    1,populate的源参数对象只接收Map类型
    2,key值得符合dest bean的命名规范, 才能进行值copy.

    三,扩展源值对象的类型支持
    在一般J2EE WEB应用开发中,可能出现值copy的地方一般会有两种:
    1, 从ResultSet对象中提取数据,送入Bean
    2, 从HttpServletRequest对象中提取数据,送入Bean.同前述ActionForm
    情况1往往会出现在读取数据库进行业务展现时,而情况2则反之,是从获取从前台提交的数据做业务处理,然后写表.

    而我个人还会碰一种情况.
    在DWR做辅助开发时,如果需要向一个后台DAO对象传送多个页面参数时,我喜欢用prototype提供的一个方法:
    Form.serialize( $(’someForm’) )
    这个方法,可以直接将Form上所有表单元素,生成key=value的标准Http GET参数串形式,然后我会将此串直接传入DWR后台业务对象处理.
    这样不但省掉了定义多个方法参数的麻烦,也便于参数个数的任意调整,应对需求变化很实用.
    那对于这种 key=value的字符串参数,我需要也能直接进行值copy,绑定到bean才行.

    当然,除了上面的ResultSet, HttpServletRequest, String三类,beanutils默认支持的Map,普通Bean当然也需要在考虑之中.
    这一步的修改,比较简单.我们只要将这几种类型统一转成Map,再用beanutils的populate即可.
    内部实现代码如下:

    1. public static void setValues(Object dest, Object src) throws Exception {
    2.         Map propAliasMap = getPropertyAliasMap
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值