Apache Commons Lang介绍

来源:互联网 发布:吴雨霏 我本人 知乎 编辑:程序博客网 时间:2024/05/02 01:07
开源工具系列文章: 
      Apache Commons Lang(1):http://ray-yui.iteye.com/blog/1953020 
      Apache Commons Lang(2):http://ray-yui.iteye.com/blog/1958319 
      Apache Commons BeanUtils:http://ray-yui.iteye.com/blog/1961451 



      在笔者之前的文章提到过,在BeanUtils中通过PropertyUtils取代了FieldUtils,PropertyUtils是一套很容易操作类属性的API工具类,使用非常简单而且保持了对类的封装,使用get和set进行存取 

Java代码  收藏代码
  1. public class TestMain {  
  2.     public static void main(String[] args) throws IllegalAccessException,  
  3.             InvocationTargetException, NoSuchMethodException {  
  4.         // 初始化信息  
  5.         Test test = new Test();  
  6.         Integer[] testArray = new Integer[10];  
  7.         Map<String, String> testMap = new HashMap<String, String>();  
  8.   
  9.           
  10.         // 以下方法名为set开始的方法均有get方法与其对应  
  11.   
  12.           
  13.         // 设置username,testArray,testMap属性  
  14.         PropertyUtils.setProperty(test, "username""Hello");  
  15.         PropertyUtils.setProperty(test, "testArray", testArray);  
  16.         PropertyUtils.setProperty(test, "testMap", testMap);  
  17.   
  18.           
  19.         // 设置testArray属性下标为0的值为10  
  20.         PropertyUtils.setIndexedProperty(test, "testArray[0]"10);  
  21.   
  22.           
  23.         // 设置testMap属性的值为参数三,遗憾是 key参数只支持字符串  
  24.         PropertyUtils.setMappedProperty(test, "testMap""Hello""10");  
  25.   
  26.           
  27.         // 在类中有嵌套类的时候,就不能使用简单的setProperty来对引用类设置属性,  
  28.         // 要使用nested,address为test类中属性名引用  
  29.         PropertyUtils.setNestedProperty(test, "address.id"1);  
  30.   
  31.           
  32.         // 判断属性是否有get方法或set方法  
  33.         PropertyUtils.isReadable(test, "username");  
  34.         PropertyUtils.isWriteable(test, "username");  
  35.   
  36.           
  37.         // 返回该实例全部属性,属性名为key,值为value  
  38.         Map<String, Object> map = PropertyUtils.describe(test);  
  39.   
  40.           
  41.         // 把test对象的所有属性复制到test2对象当中,  
  42.         // 通过反射字段名匹配进行复制,但要注意将会覆盖原值  
  43.         Test test2 = new Test();  
  44.         PropertyUtils.copyProperties(test2, test);  
  45.   
  46.   
  47.         // 获取属性的Class类型  
  48.         PropertyUtils.getPropertyType(test, "username");  
  49.     }  
  50. }  


PropertyUtils和BeanUtils的方法非常相似,但有一些小细节上可以区别它们,例如都使用copyProperty,BeanUtils只要属性名一致就算类型不同都可以互相兼容赋值,但PropertyUtils则会报错 

Java代码  收藏代码
  1. public class TestMain {  
  2.     public static void main(String[] args) throws IllegalAccessException,  
  3.             InvocationTargetException, NoSuchMethodException,  
  4.             InstantiationException {  
  5.         Test test1 = new Test();  
  6.         Test test2 = new Test();  
  7.   
  8.           
  9.         // 复制单个属性  
  10.         BeanUtils.copyProperty(test1, "username", test2);  
  11.   
  12.           
  13.         // 克隆对象,注意是浅克隆  
  14.         Test test3 = (Test) BeanUtils.cloneBean(test1);  
  15.   
  16.           
  17.         /* 
  18.          * 在设置时间时,读者需要注意一个小问题,  
  19.          * 用-->setProperty(test1, "date", new Date()); 
  20.          * 这种方式设置时间时没有问题的,但若然使用字符串的形式2013-10-3 
  21.          * 就会出现问题,这是因为BeanUtils无法识别字符串类型和时间类型的关系, 
  22.          * 所以我们需要使用ConvertUtils来辅助BeanUtils, 
  23.          * 但使用如下方式进行转换后,PropertyUtils仍然是无能为力 
  24.          */  
  25.           
  26.         //用此种方式没任何问题  
  27.         BeanUtils.setProperty(test1, "date"new Date());   
  28.         //此种方式无法区别字符串还是日期  
  29.         BeanUtils.setProperty(test1, "date""2013-10-01");  
  30.   
  31.           
  32.         // 自定义一个转换器  
  33.         ConvertUtils.register(new Converter() {  
  34.   
  35.             @Override  
  36.             public Object convert(Class type, Object value) {  
  37.                 if (value == null) {  
  38.                     throw new RuntimeException("value is null");  
  39.                 }  
  40.                 if (value.getClass() == Date.class) {  
  41.                     return value;  
  42.                 }  
  43.                 if (value.getClass() != String.class) {  
  44.                     throw new RuntimeException("type not match");  
  45.                 }  
  46.                 String valueStr = (String) value;  
  47.                 if (StringUtils.isBlank(valueStr)) {  
  48.                     throw new RuntimeException("string is empty");  
  49.                 }  
  50.                 try {  
  51.                     return new SimpleDateFormat("yyyy-MM-dd").parse(valueStr);  
  52.                 } catch (ParseException e) {  
  53.                     e.printStackTrace();  
  54.                     return null;  
  55.                 }  
  56.             }  
  57.         }, Date.class);  
  58.   
  59.         // 此时使用字符串的日期形式都可以成功转换  
  60.         BeanUtils.setProperty(test1, "date""2013-10-1");  
  61.     }  
  62. }  


      从上面时间转换的例子就能看出,为什么同属性名不同类型PropertyUtils会转换失败,因为PropertyUtils并没有使用ConvertUtils来进行转换,导致类型不同时没发互相转换,由于Apache commons发展历史的原因,导致某些Utils功能大致相同,请读者自行选择 


      在某些业务情况下,我们的Bean是不确定的,可能随某些地方触发而改变,可能需要某个属性,又可能不需要某个属性,这种动态的Bean是编译性语言的Java无法支持的,但BeanUtils中的自由Bean(动态Bean)将动态创建Bean成为了可能 

Java代码  收藏代码
  1. public class TestMain {  
  2.     public static void main(String[] args) throws IllegalAccessException,  
  3.             InstantiationException {  
  4.   
  5.         // 创建动态Bean所拥有的字段  
  6.         DynaProperty[] props = new DynaProperty[] {  
  7.                 new DynaProperty("id", String.class),  
  8.                 new DynaProperty("testMap", Map.class) };  
  9.   
  10.           
  11.         // 创建dynaClass的BasicDynaClass实现,传入定义的props  
  12.         DynaClass dynaClass = new BasicDynaClass("bean"null, props);  
  13.   
  14.           
  15.         // 通过dynaClass创建Bean  
  16.         DynaBean bean = dynaClass.newInstance();  
  17.   
  18.           
  19.         // 可以按普通bean的方式对其进行使用  
  20.         bean.set("id""hello");  
  21.         bean.set("testMap"new HashMap());  
  22.         bean.set("testMap""Hello""World");  
  23.   
  24.         bean.get("id");  
  25.         bean.get("testMap""Hello");  
  26.   
  27.   
  28.         /* 
  29.          * BasicDynaClass是DynaClass接口的实现类,  
  30.          * 其中还有LazyDynaClass的实现可以帮助我们更方便 
  31.          * 的使用动态bean,lazy,懒嘛!方便 
  32.          */  
  33.   
  34.         // 不需要再定义dynaProperty,直接赋值时将会自动声明属性  
  35.         DynaClass dynaClass = new LazyDynaClass();  
  36.   
  37.         DynaBean dynaBean = dynaClass.newInstance();  
  38.   
  39.         dynaBean.set("username""Hello");  
  40.         dynaBean.set("testArray"0"Hello");  
  41.         dynaBean.set("testMap""Hello""World");  
  42.   
  43.         dynaBean.get("username");  
  44.         dynaBean.get("testArray"0);  
  45.         dynaBean.get("testMap""Hello");  
  46.   
  47.     }  
  48. }  


总结: 
      commons工具包很多开源组织都有提供,例如google,spring,apache都有各自的工具包,有众多的选择,但最终的目的只是为了方便我们程序的开发和维护,简化我们编写一些常用的逻辑,提升我们开发的效率,从而达到活在开源,善用开源