1.概述
在项目中遇到要将数据库对象转换为领域对象,不想一个个写set(get()),也不想自己去写反射,于是比较了一下开源的几个工具类。个人了解的有apache的BeanUtils,PropertiesUitls,还有spring的BeanUtils。纠结于哪个更合适,于是比较了一下。
2.比较
apache PropertiesUtils | apache BeanUtils | spring BeanUtils | ||
实现复杂度 | 复杂 | 复杂 | 简单 | |
功能特点 | 将源对象中和目标对象同名的属性(浅拷贝),同名不同类 型抛异常(checked exception) | 同前,提供同名不同类型的 类型转换并支持扩展 | 同PropertiesUtils | |
性能 | 3个属性的对象,拷贝100w次 个人电脑2000ms | 5000ms | 600ms |
综上所述,个人这个case是spring的BeanUtils更合适。apache的虽然更强大(考虑的细节和分支条件更多),
但暂时用不到,而且性能差距还是比较明显。
对于转换类为map的describe方法,spring的Utils没有,但很容易利用他现有方法扩展:
- public static Map<String, Object> describe(Object source) {
- Assert.notNull(source, "Source must not be null");
- HashMap<String, Object> result = new HashMap<String, Object>();
- Class<?> clazz = source.getClass();
- PropertyDescriptor[] sourcePds = BeanUtils.getPropertyDescriptors(clazz);
- for (int i = 0; i < sourcePds.length; i++) {
- PropertyDescriptor sourcePd = sourcePds[i];
- String name = sourcePd.getName();
- if (ignoreList.contains(name)) {
- continue;
- }
- try {
- Method readMethod = sourcePd.getReadMethod();
- if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
- readMethod.setAccessible(true);
- }
- Object value = readMethod.invoke(source, new Object[0]);
- result.put(name, value);
- } catch (Throwable e) {
- throw new FatalBeanException("Could not copy properties from source to HashMap", e);
- }
- }
- return result;
- }
3.总结
首先是否用反射来拷贝,本来就是在开发速度和运行速度之间的一个权衡。考虑到性能损耗在不大(对于本应用的性能需求来说),所以选择用反射工具。
对于性能,spring比较快主要是因为逻辑简单些,而且缓存了BeanInfo信息,同样的类不用每次都取。也算是空间换时间,当然更激进一点,可以像fastjson一样,用字节码方式把每个类型对生成一个拷贝类,时间上就和直接get,set差不多了。