Java高新技术 JavaBean内省
Java高新技术 JavaBean内省
知识概要:
(1)了解JavaBean内省
(2)JavaBean的简单内省操作
(3)使用BeanUtils来操作JavaBean
了解JavaBean内省
JavaBean是一种特殊的Java类,主要用于传递数据信息,
这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。
如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,
这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO)。
这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,
则需要通过一些相应的方法来访问,大家觉得这些方法的名称叫什么好呢?
JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。
如果方法名为setId,中文意思即为设置id,至于你把它存到哪个变量上,用管吗?如果方法名为getId,中文意 思即为获取id,至于你从哪个变量上取,用管吗?去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个 字母是小写的,则把剩余部分的首字母改成小的。
setId()的属性id
isLast()的属性名last
setCPU的属性名是什么? CPU
getUPS的属性名是什么? UPS
总之,一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,
它根本看不到java类内部的 成员变量。
一个符合JavaBean特点的类可以当作普通类一样进行使用,但把它当JavaBean用肯定需要带来一些额外的好 处,我们才会去了解和应用JavaBean!好处如下:
在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作,
别人都这么用和要求 这么做,那你就没什么挑选的余地!
JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。如果要你自己去通过getX方法来访问私有 的x,怎么做,有一定难度吧?用内省这套api操作JavaBean比用普通类的方式更方便。
内省综合案例
直接new一个PropertyDescriptor对象的方式来让大家了解JavaBean API的价值,
演示用eclipse将读取属性和设置属性的流水帐代码分别抽取成方法:
只要调用这个方法,并给这个方法传递了一个对象、属性名和设置值,它就能完成属性修改的功能。
得到BeanInfo最好采用“obj.getClass()”方式,而不要采用“类名.class”方式,这样程序更通用。
采用遍历BeanInfo的所有属性方式来查找和设置某个RefectPoint对象的x属性。在程序中把一个类当作JavaBean来
package cn.itheima.day1; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.PropertyUtils; public class IntroSPectorTest { public static void main(String[] args) throws Exception{ ReflectPoint pt1 = new ReflectPoint(3,5);; String propertyName = "x"; Object retVal = getProperty(pt1, propertyName); System.out.println(retVal); Object value = 7; setProperties(pt1, propertyName, value); System.out.println(BeanUtils.getProperty(pt1,"x")); BeanUtils.setProperty(pt1,"x","9"); System.out.println(BeanUtils.getProperty(pt1,"x")); //java7新特性。 //Map map =(name:"cuizhaojin",age:18); //BeanUtils.setProperty(map, "name", "cuizhao"); BeanUtils.setProperty(pt1,"birthday.time","2014"); String birthday = BeanUtils.getProperty(pt1,"birthday.time"); System.out.println(birthday); PropertyUtils.setProperty(pt1,"x",9); System.out.println(PropertyUtils.getProperty(pt1, "x").getClass()); } private static void setProperties(Object pt1, String propertyName, Object value) throws IntrospectionException, IllegalAccessException, InvocationTargetException { PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass()); Method methodSetX =pd2.getWriteMethod(); methodSetX.invoke(pt1,value); } private static Object getProperty(Object pt1, String propertyName) throws Exception /*throws IntrospectionException, IllegalAccessException, InvocationTargetException { PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass()); Method methodGetX =pd.getReadMethod(); Object retVal = methodGetX.invoke(pt1);*/{ BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass()); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); Object retVal = null; for(PropertyDescriptor pd: pds) { if(pd.getName().equals(propertyName)) { Method methodGetX = pd.getReadMethod(); retVal = methodGetX.invoke(pt1); break; } } return retVal; } }
图例:
PropertyUtils类也可以操作对象的属性,但是与BeanUtils不同的是它不能进行自动类型转换。
例如Person类中的age属性为int类型,但是设置属性值的时候传入的参数就不可以是String类型。
如果设置成了String类型,那么将会报错。