设为首页 收藏本站
查看: 853|回复: 0

[经验分享] Spring 中的BeanUtils与apache中的BeanUtils用法与比较

[复制链接]

尚未签到

发表于 2015-8-1 08:14:38 | 显示全部楼层 |阅读模式
  Apache BeanUtil简介。
  Apache Common BeanUtil是一个常用的在对象之间复制数据的工具类,著名的web开发框架struts就是依赖于它进行ActionForm的创建。

    BeanUtil最常用的类是org.apache.commons.beanutils.BeanUtils。
    BeanUtils最常用的方法为:
    1.   public void copyProperties(java.lang.Object dest, java.lang.Object orig)
把orig中的值copy到dest中.
    2.   public java.util.Map describe(java.lang.Object bean)
把Bean的属性值放入到一个Map里面。
    3.public void populate(java.lang.Object bean, java.util.Map properties)
把properties里面的值放入bean中。
    4.   public void setProperty(java.lang.Object bean, java.lang.String name, java.lang.Object value)
设置Bean对象的名称为name的property的值为value.
    5.   public String getProperty(java.lang.Object bean, java.lang.String name)
        取得bean对象中名为name的属性的值。
    详细的使用方法可以参见官方网站:
    http://jakarta.apache.org/commons/beanutils/

  Apache Common BeanUtil常见使用场景

1.     同类之间不同对象要求进行数据复制。




User user1 = …;
User user2 = …;
BeanUtils. copyProperties(user2,user1);
2.     不同类不同对象之间的数据复制。




UserForm userForm = …;
User user = …;
BeanUtils. copyProperties(user, userForm);
相信经常使用struts的人,一定会很熟悉上面的代码。
这是一个典型把页面的value object数据复制到domain object的例子。
3.     对象数据和Map之间互相转化。



User user = …;
Map userMap = BeanUtils.describe(user);
Map userMap = …;
User user = …;
BeanUtils.populate(user,userMap);
   Map可以看成一个动态数据容器,作为VO很适合在不同层之间传播数据,作为PO也可以动态存储字段信息,
合理运用可以减少程序很多修改和维护工作。所以让bean和map之间方便的进行数据填充,非常必要。

  Apache Common BeanUtil的支持类型的扩展。

  BeanUtils能够顺利的完成对象属性值的复制,依赖于其对类型的识别。在org.apache.commons.beanutils.converters包中有一系列converter类,用于不同类型之间对象的转化。比如说BigDecimalConverter,显然,就是用来转化BigDecimal的。这里面基本的类型已经写得很全了。如果需要扩展BeanUtil的类型支持,必须要自己写Converter去实现org.apache.commons.beanutils.Converter接口。扩展只要找一个具体的Converter类照着修改就好了。

这是一个最简单的例子。




public class MyTypeConverter implements Converter {
    private boolean useDefault = false;
    private Object defaultValue = null;
    public MyConverter(Object defaultValue) {
        useDefault = false;
        if (defaultValue == null) {
           this.defaultValue  = null;
        } else {
           this.defaultValue  = defaultValue;
        }
        useDefault = true;
    }
    public Object convert(Class type, Object value) {
        if(value == null){
            if(useDefault){
                   return defaultValue;
           }else{
                   Throw new ConvertException(…);
           }               
        }
        if(value.getClass().equals(type))
               return value;
        else
               return value.toString();
    }
}
另外一个简单的办法是直接继承AbstractConverter。




public class MyTypeConverter implements AbstractConverter{
   protected Object convertToType(Class type, Object value) throws Exception{
       //…
   }
}

Defaultvalue之类的设定就做了默认处理。可以只考虑转化到除了String以外其他类型时的情况。
Converter具体类在写完后需要注册到BeanUtils系统才可以用。通过ConvertUtils.register(Converter converter,Class clazz)这个静态方法,我们就可以把一个具体的Converter邦定到一个Class。每次当BeanUtils试图处理这种Class类型的属性时,就会调用已经注册到这个Class上的Converter.

Converter类和如何注册的问题解决了,那么何时注册比较好呢?最好是和BeanUtils默认的Connvertor同时注册。ConvertUtils的方法都是委派到ConvertUtilsBean.getInstance()返回的一个单例上来执行的。

ConvertUtilsBean的构造器如下:




public ConvertUtilsBean() {
        converters.setFast(false);
        //就是这句。
        deregister();
        converters.setFast(true);
}

deregister()代码如下:



public void deregister() {
        boolean booleanArray[] = new boolean[0];
        byte byteArray[] = new byte[0];
        …
        converters.clear();
        register(BigDecimal.class, new BigDecimalConverter());
        register(BigInteger.class, new BigIntegerConverter());
        register(Boolean.TYPE, new BooleanConverter(defaultBoolean));
        register(Boolean.class,  new BooleanConverter(defaultBoolean));
        …
}

问题来了,这是硬编码的,一般还是不要修改原代码的好。其实这块部分适合作成一个配置,但是BeanUtil的作者尽量保持简单的关系。
我们还有机会在外面注册Convertor以添加或者替换BeanUtil默认的Converter。
这种工具类的初始化总该在我们的业务逻辑运行起来之前就完成的。那么自然比如是个web程序,
就可以把register的工作放到初始化就运行的servlet或者listener上去。



Public class MyServerlet{
        public void init(){
                ConvertUtils.register(MyTypeConverter,MyType.class);
        }
}
很显然,我们依然通过代码进行了配置,而且一旦脱离了servlet环境,将不再可用。
  Apache Common BeanUtil的Spring配置。
  如果我们采用IOC框架,那么可以通过优雅的配置对BeanUtil进行自己的定制。

以spring为例我们做如下配置。







        
              
                  
                     java.sql.Timestamp
                  
                  
              
      
   


   
      
   
beanUtilsConfig类:




public class BeanUtilsConfig implements InitializingBean{
        private Map converters = new HashMap();
        public void afterPropertiesSet() throws Exception {
               Set keys = converters.keySet();
               for(Object key:keys){
                       ConvertUtils.register((Converter)converters.get(key),Class.forName((String) key));
               }
        }
        public Map getConverters() {
               return converters;
        }
        public void setConverters(Map converterMap) {
               this.converters = converterMap;
        }
}
这样就完成了在spring框架启动的时候,注册Converter类,
修改sqlTimestampConverter的Converter为默认值为null的Converter。
当然,在调用ConvertUtils.register之前,BeanUtil的默认Convertor已经注册完成。
由上可以看出IOC容器对于改进我们的设计非常有帮助,如果BeanUtil基于IOC容器开发的话,其可配置性将大大增强。





BeanUtils的使用-在具有很多相同属性的两个bean之间复制属性值


   import org.springframework.beans.BeanUtils;
  注意事项:
  在使用时一定要用import org.springframework.beans.BeanUtils;包里的BeanUtils。
  因为在用的过程中 使用import org.apache.commons.beanutils.BeanUtils时,bean里含有Date类型(时间)值时(尤其date=null时),很容易出错。
  
  
  在两个具有很多相同属性的bean,直接将一个bean的属性值复制给另一个bean的属性。
  如果两个bean之 间存在名称不相同的属性,则BeanUtils不对这些属性进行处理,需要手动处理。
  
  帮程序员节省了大量代码的同时,也消耗了大量的时间。
  BeanUtils 好处:使用方便,代码简单明了。
                   坏处:在java1.4及之前会 消耗大量时间。
  用还是不用,这是个问题??
  
  BeanUtils.copyProperties(beanSource, beanMuBiao); //permissionModel为源,beanMuBiao目标(将他两共有的属性赋给beanMuBiao)。
  
  关于import org.apache.commons.beanutils.BeanUtils的一些该注意的地方:
  BeanUtils支持的转换类型如下:    * java.lang.BigDecimal    * java.lang.BigInteger    * boolean and java.lang.Boolean    * byte and java.lang.Byte    * char and java.lang.Character    * java.lang.Class    * double and java.lang.Double    * float and java.lang.Float    * int and java.lang.Integer    * long and java.lang.Long    * short and java.lang.Short    * java.lang.String    * java.sql.Date    * java.sql.Time    * java.sql.Timestamp 这里要注意一点,java.util.Date是不被支持的,而它的子类java.sql.Date是被支持的。因此如果对象包含时间类型的属性,且希望被转换的时候,一定要使用java.sql.Date类型。否则在转换时会提示argument mistype异常。
  
  
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-92847-1-1.html 上篇帖子: 使用yum安装Apache+PHP+MySQL 下篇帖子: apache下ab.exe使用方法。。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表