1. 为什么要实现javaBean与Map相互转换?
用过spring的都知道spring的MVC框架中有一个BaseCommandController对象,利用这个对象我们就可以很方便的将从客户端传递过来的参数封装到一个JavaBean对象中去,而不需要我们request.getParameter("name");bean.setName(name);了,从而也简化了不少的工作。如果大家用过BeanUtils.populate的话,就知道,这个方法是可以很方便的将request提交的页面表单自动填写到你创建的对象中
2. 如何实现javaBean与Map相互转换?
方法1: 利用Java.beans.Introspector和java.beans.PropertyDescriptor实现 javaBean与Map互转
方法2: 利用org.apache.commons.beanutils.BeanUtils工具类,BeanUtils.populate实现Map 转换为javaBean
1 packagejavaStudyDemo.bean.reflect.test;2
3 importjava.beans.BeanInfo;4 importjava.beans.Introspector;5 importjava.beans.PropertyDescriptor;6 importjava.lang.reflect.Method;7 importjava.util.HashMap;8 importjava.util.Map;9 importjavaStudyDemo.others.PersonBean;10
11 importorg.apache.commons.beanutils.BeanUtils;12
13 /**
14 * 当把Person类作为BeanUtilTest的内部类时,程序出错
15 * java.lang.NoSuchMethodException: Property '**' has no setter method
16 * 本质:内部类 和 单独文件中的类的区别
17 * BeanUtils.populate方法的限制:
18 * The class must be public, and provide a public constructor that accepts no arguments.
19 * This allows tools and applications to dynamically create new instances of your bean,
20 * without necessarily knowing what Java class name will be used ahead of time21 */
22 public classBeanUtilTest {23
24 public static voidmain(String[] args) {25
26 PersonBean person = newPersonBean();27 Map mp = new HashMap();28 mp.put("name", "Mike");29 mp.put("age", 25);30 mp.put("mN", "male");31
32 //将map转换为bean
33 transMap2Bean2(mp, person);34
35 System.out.println("--- transMap2Bean Map Info: ");36 for (Map.Entryentry : mp.entrySet()) {37 System.out.println(entry.getKey() + ": " +entry.getValue());38 }39
40 System.out.println("--- Bean Info: ");41 System.out.println("name: " +person.getName());42 System.out.println("age: " +person.getAge());43 System.out.println("mN: " +person.getmN());44
45 //将javaBean 转换为map
46 Map map =transBean2Map(person);47
48 System.out.println("--- transBean2Map Map Info: ");49 for (Map.Entryentry : map.entrySet()) {50 System.out.println(entry.getKey() + ": " +entry.getValue());51 }52
53 }54
55 //Map --> Bean 2: 利用org.apache.commons.beanutils 工具类实现 Map --> Bean
56 public static void transMap2Bean2(Mapmap, Object obj) {57 if (map == null || obj == null) {58 return;59 }60 try{61 BeanUtils.populate(obj, map);62 } catch(Exception e) {63 System.out.println("transMap2Bean2 Error " +e);64 }65 }66
67 //Map --> Bean 1: 利用Introspector,PropertyDescriptor实现 Map --> Bean
68 public static void transMap2Bean(Mapmap, Object obj) {69
70 try{71 BeanInfo beanInfo =Introspector.getBeanInfo(obj.getClass());72 PropertyDescriptor[] propertyDescriptors =beanInfo.getPropertyDescriptors();73
74 for(PropertyDescriptor property : propertyDescriptors) {75 String key =property.getName();76
77 if(map.containsKey(key)) {78 Object value =map.get(key);79 //得到property对应的setter方法
80 Method setter =property.getWriteMethod();81 setter.invoke(obj, value);82 }83
84 }85
86 } catch(Exception e) {87 System.out.println("transMap2Bean Error " +e);88 }89
90 return;91
92 }93
94 //Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map
95 public static MaptransBean2Map(Object obj) {96
97 if(obj == null){98 return null;99 }100 Map map = new HashMap();101 try{102 BeanInfo beanInfo =Introspector.getBeanInfo(obj.getClass());103 PropertyDescriptor[] propertyDescriptors =beanInfo.getPropertyDescriptors();104 for(PropertyDescriptor property : propertyDescriptors) {105 String key =property.getName();106
107 //过滤class属性
108 if (!key.equals("class")) {109 //得到property对应的getter方法
110 Method getter =property.getReadMethod();111 Object value =getter.invoke(obj);112
113 map.put(key, value);114 }115
116 }117 } catch(Exception e) {118 System.out.println("transBean2Map Error " +e);119 }120
121 returnmap;122
123 }124 }
1 public classPersonBean {2
3 privateString name;4 privateInteger age;5 privateString mN;6
7 /**
8 *@returnthe mN9 */
10 publicString getmN() {11 returnmN;12 }13
14 /**
15 *@parammN the mN to set16 */
17 public voidsetmN(String mN) {18 this.mN =mN;19 }20
21
22 /**
23 *@returnthe name24 */
25 publicString getName() {26 returnname;27 }28
29 /**
30 *@paramname the name to set31 */
32 public voidsetName(String name) {33 this.name =name;34 }35
36 /**
37 *@returnthe age38 */
39 publicInteger getAge() {40 returnage;41 }42
43 /**
44 *@paramage the age to set45 */
46 public voidsetAge(Integer age) {47 this.age =age;48 }49
50 }
总结: javaBean与Map互转利用到了java的内省( Introspector )和反射(reflect)机制。 其思路为: 通过类 Introspector 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器PropertyDescriptor,再利用属性描述器获取某个属性对应的 getter/setter 方法,然后通过反射机制来getter和setter。
什么是内省?
内省是 Java 语言对 Bean 类属性、事件的一种缺省处理方法。例如类 PersonBean中有属性 name, 那我们可以通过 getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这就是默认的规则。 Java 中提供了一套 API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则(但你最好还是要搞清楚),这些 API 存放于包 java.beans 中。注意: PersonBean中属性mN的getter/setter方法必须满足javaBean命名规范,即getmN,不能写作getMN,否则转换失败。
已验证;