开源工具系列文章:
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进行存取
PropertyUtils和BeanUtils的方法非常相似,但有一些小细节上可以区别它们,例如都使用copyProperty,BeanUtils只要属性名一致就算类型不同都可以互相兼容赋值,但PropertyUtils则会报错
从上面时间转换的例子就能看出,为什么同属性名不同类型PropertyUtils会转换失败,因为PropertyUtils并没有使用ConvertUtils来进行转换,导致类型不同时没发互相转换,由于Apache commons发展历史的原因,导致某些Utils功能大致相同,请读者自行选择
在某些业务情况下,我们的Bean是不确定的,可能随某些地方触发而改变,可能需要某个属性,又可能不需要某个属性,这种动态的Bean是编译性语言的Java无法支持的,但BeanUtils中的自由Bean(动态Bean)将动态创建Bean成为了可能
总结:
commons工具包很多开源组织都有提供,例如google,spring,apache都有各自的工具包,有众多的选择,但最终的目的只是为了方便我们程序的开发和维护,简化我们编写一些常用的逻辑,提升我们开发的效率,从而达到活在开源,善用开源
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进行存取
- public class TestMain {
- public static void main(String[] args) throws IllegalAccessException,
- InvocationTargetException, NoSuchMethodException {
- // 初始化信息
- Test test = new Test();
- Integer[] testArray = new Integer[10];
- Map<String, String> testMap = new HashMap<String, String>();
- // 以下方法名为set开始的方法均有get方法与其对应
- // 设置username,testArray,testMap属性
- PropertyUtils.setProperty(test, "username", "Hello");
- PropertyUtils.setProperty(test, "testArray", testArray);
- PropertyUtils.setProperty(test, "testMap", testMap);
- // 设置testArray属性下标为0的值为10
- PropertyUtils.setIndexedProperty(test, "testArray[0]", 10);
- // 设置testMap属性的值为参数三,遗憾是 key参数只支持字符串
- PropertyUtils.setMappedProperty(test, "testMap", "Hello", "10");
- // 在类中有嵌套类的时候,就不能使用简单的setProperty来对引用类设置属性,
- // 要使用nested,address为test类中属性名引用
- PropertyUtils.setNestedProperty(test, "address.id", 1);
- // 判断属性是否有get方法或set方法
- PropertyUtils.isReadable(test, "username");
- PropertyUtils.isWriteable(test, "username");
- // 返回该实例全部属性,属性名为key,值为value
- Map<String, Object> map = PropertyUtils.describe(test);
- // 把test对象的所有属性复制到test2对象当中,
- // 通过反射字段名匹配进行复制,但要注意将会覆盖原值
- Test test2 = new Test();
- PropertyUtils.copyProperties(test2, test);
- // 获取属性的Class类型
- PropertyUtils.getPropertyType(test, "username");
- }
- }
PropertyUtils和BeanUtils的方法非常相似,但有一些小细节上可以区别它们,例如都使用copyProperty,BeanUtils只要属性名一致就算类型不同都可以互相兼容赋值,但PropertyUtils则会报错
- public class TestMain {
- public static void main(String[] args) throws IllegalAccessException,
- InvocationTargetException, NoSuchMethodException,
- InstantiationException {
- Test test1 = new Test();
- Test test2 = new Test();
- // 复制单个属性
- BeanUtils.copyProperty(test1, "username", test2);
- // 克隆对象,注意是浅克隆
- Test test3 = (Test) BeanUtils.cloneBean(test1);
- /*
- * 在设置时间时,读者需要注意一个小问题,
- * 用-->setProperty(test1, "date", new Date());
- * 这种方式设置时间时没有问题的,但若然使用字符串的形式2013-10-3
- * 就会出现问题,这是因为BeanUtils无法识别字符串类型和时间类型的关系,
- * 所以我们需要使用ConvertUtils来辅助BeanUtils,
- * 但使用如下方式进行转换后,PropertyUtils仍然是无能为力
- */
- //用此种方式没任何问题
- BeanUtils.setProperty(test1, "date", new Date());
- //此种方式无法区别字符串还是日期
- BeanUtils.setProperty(test1, "date", "2013-10-01");
- // 自定义一个转换器
- ConvertUtils.register(new Converter() {
- @Override
- public Object convert(Class type, Object value) {
- if (value == null) {
- throw new RuntimeException("value is null");
- }
- if (value.getClass() == Date.class) {
- return value;
- }
- if (value.getClass() != String.class) {
- throw new RuntimeException("type not match");
- }
- String valueStr = (String) value;
- if (StringUtils.isBlank(valueStr)) {
- throw new RuntimeException("string is empty");
- }
- try {
- return new SimpleDateFormat("yyyy-MM-dd").parse(valueStr);
- } catch (ParseException e) {
- e.printStackTrace();
- return null;
- }
- }
- }, Date.class);
- // 此时使用字符串的日期形式都可以成功转换
- BeanUtils.setProperty(test1, "date", "2013-10-1");
- }
- }
从上面时间转换的例子就能看出,为什么同属性名不同类型PropertyUtils会转换失败,因为PropertyUtils并没有使用ConvertUtils来进行转换,导致类型不同时没发互相转换,由于Apache commons发展历史的原因,导致某些Utils功能大致相同,请读者自行选择
在某些业务情况下,我们的Bean是不确定的,可能随某些地方触发而改变,可能需要某个属性,又可能不需要某个属性,这种动态的Bean是编译性语言的Java无法支持的,但BeanUtils中的自由Bean(动态Bean)将动态创建Bean成为了可能
- public class TestMain {
- public static void main(String[] args) throws IllegalAccessException,
- InstantiationException {
- // 创建动态Bean所拥有的字段
- DynaProperty[] props = new DynaProperty[] {
- new DynaProperty("id", String.class),
- new DynaProperty("testMap", Map.class) };
- // 创建dynaClass的BasicDynaClass实现,传入定义的props
- DynaClass dynaClass = new BasicDynaClass("bean", null, props);
- // 通过dynaClass创建Bean
- DynaBean bean = dynaClass.newInstance();
- // 可以按普通bean的方式对其进行使用
- bean.set("id", "hello");
- bean.set("testMap", new HashMap());
- bean.set("testMap", "Hello", "World");
- bean.get("id");
- bean.get("testMap", "Hello");
- /*
- * BasicDynaClass是DynaClass接口的实现类,
- * 其中还有LazyDynaClass的实现可以帮助我们更方便
- * 的使用动态bean,lazy,懒嘛!方便
- */
- // 不需要再定义dynaProperty,直接赋值时将会自动声明属性
- DynaClass dynaClass = new LazyDynaClass();
- DynaBean dynaBean = dynaClass.newInstance();
- dynaBean.set("username", "Hello");
- dynaBean.set("testArray", 0, "Hello");
- dynaBean.set("testMap", "Hello", "World");
- dynaBean.get("username");
- dynaBean.get("testArray", 0);
- dynaBean.get("testMap", "Hello");
- }
- }
总结:
commons工具包很多开源组织都有提供,例如google,spring,apache都有各自的工具包,有众多的选择,但最终的目的只是为了方便我们程序的开发和维护,简化我们编写一些常用的逻辑,提升我们开发的效率,从而达到活在开源,善用开源