javaBean & introspector(内省)
javaBean是一种特殊的java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有字段,且方法名符合某种命名规则.
如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种javaBean的实例对象通常称之为值对象(Value Object)简称VO.这些信息在类中用私有字段存储,如果读取设置这些字段的值,则需要通过一些相应的方法来访问.javaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其变量.如果方法名为setID,中文意思是设置ID,至于你把它存在哪个变量上,用管吗?
总之,一个类被当成javaBean使用时,其属性是根据方法名推断出来的,它根本看不到java类内部的成员变量.
一个符合javaBean特点的类可以当做普通类一样进行使用,,但把它当成javaBean用肯定需要带来一些额外的好处.
在javaEE开发中,经常使用到javaBean.很多环境就要求按照javaBean方式进行操作.
JDK中提供了对javaBean进行操作的一些API,这套api就称为内省.
1.对JavaBean的简单内省操作
通过创建一个PropertyDescription对象的方式获取Point对象属性描述信息,然后通过反射的放射方法获取和更改属性值.
为了演示先创建一个Point类,该类按照JavaBean格式建立:
package com.heima;
public class Point {
private int x;
private int y;
private String name;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
建立一个JavaBeanDemo类,该类主要演示了,获取Point类实例的属性及对属性值的修改.
package com.heima;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class JavaBeanDemo {
public static void main(String[] args) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//创建一个Point实例对象
Point point=new Point(1,2);
//创建一个PropertyDescription对象,并将要操作的对象和属性作为参数传递进去
//这里操作的是Point类的x属性
PropertyDescriptor pd=new PropertyDescriptor("x",point.getClass());
//该函数展示获取point的x属性值
showGetProperty(point, pd);
//该函数展示设置point的x属性值
showSetProperty(point, pd);
}
//定义一个函数用于获取x的值
private static void showSetProperty(Point point, PropertyDescriptor pd)
throws IllegalAccessException, InvocationTargetException {
//建立一个Method对象,该方法其实用的还是反射的知识
Method method2=pd.getWriteMethod();
//使用获取到的方法
method2.invoke(point,200);
System.out.println(point.getX());
}
//定义一个函数用于改变x的值
private static void showGetProperty(Point point, PropertyDescriptor pd)
throws IllegalAccessException, InvocationTargetException {
//建立一个Method方法对象,获取Point类的方法
Method method=pd.getReadMethod();
//打印获取到的方法
System.out.println(method);
//调用获取到的方法
Object obj=method.invoke(point);
System.out.println(obj);
}
}
2.对JavaBean的复杂操作
采用遍历BeanInfo的所有属性方法来查找和设置某个Point对象的属性的值.通过调用IntroSpector.getBeanInfo方法,得到BeanInfo对象封装了把这个类当做JavaBean看的结果信息.
// 定义一个函数用于设置x的值
private static void showSetProperty2(Point point)
throws IllegalAccessException, InvocationTargetException,
IntrospectionException {
//BeanInfo是一个接口,因此可以通过Introspector的静态方法会获取其实现类的实例
BeanInfo beanInfo = Introspector.getBeanInfo(point.getClass());
//通过beanInfo获取所以属性描述,存储在数组中
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
for (int i = 0; i < pds.length; i++) {//通过for循环遍历pds,
if ("x".equals(pds[i].getName())) {//如果找到属性x则
showSetProperty(point, pds[i]);//调用showSetProperty(point, pds[i])
//方法对其属性值进行操作
}
}
}
// 定义一个函数用于获取x的值
private static void showGetProperty2(Point point)
throws IllegalAccessException, InvocationTargetException, IntrospectionException {
BeanInfo beanInfo = Introspector.getBeanInfo(point.getClass());
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
for (int i = 0; i < pds.length; i++) {
if ("x".equals(pds[i].getName())) {
showGetProperty(point,pds[i]);
}
}
}
该方法显然没有第一种方法简单.
3.使用BeanUtils工具包对JavaBean的操作
BeanUtils提供对 Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性.
在使用BeanUtils前,先将该工具导入工程中.
步骤
1.在工程下新建一个lib文件夹,把log4j.jar,commons-beanutils-1.8.0.jar复制到lib文件夹下(commons-beanutils-1.8.0.jar需要commons-logging.jar包支持)
2. 把lib下的commons-beanutils-1.8.0.jar,commons-logging.jar加入到classpath(构建路径)
选中jar右击——Builb Path——Add to Build Path
为了演示BeanUtils对复合属性的操作,在Point类中增加一个Date类型的属性
: private Date birthday=new Date();
// 定义一个函数用于设置x的值
private static void showSetProperty3(Point point)
throws IllegalAccessException, InvocationTargetException,
IntrospectionException, NoSuchMethodException {
//通过BeanUtils设置x的属性
Object obj=BeanUtils.getProperty(point, "x");
System.out.println(obj);
//设置birthday的属性,但是由于birthday的类型时Date类型的,是一个复合类型
//因此必须参入的类型为"birthday.time",传入的数字必须是字符串形式,尽管123其实是
//Date的long类型数值
BeanUtils.setProperty(point, "birthday.time","123");
System.out.println(point.getBirthday());
}
// 定义一个函数用于获取x的值
private static void showGetProperty3(Point point)
throws IllegalAccessException, InvocationTargetException, IntrospectionException, NoSuchMethodException {
//获取"birthday.time"属性
Object obj=BeanUtils.getProperty(point, "birthday.time");
System.out.println(obj);
}