JavaBean内省:认识JavaBean与内省、对JavaBean的内省操作、Beanutils工具包

1  初识JavaBean与内省

JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。

 

如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO)。

这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。

 

JavaBean的属性是根据其中的settergetter方法来确定的,而不是根据其中的成员变量。

如果方法名为setId,中文意思即为设置id,至于你把它存到哪个变量上,则不用管。

如果方法名为getId,中文意思即为获取id,至于你从哪个变量上取,也不用管。

去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。

例如:
      setId()的属性名:id

      isLast()的属性名:last

      setCPU 的属性名: CPU
      getUPS 的属性名: UPS

总之,一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。

 

一个符合JavaBean特点的类可以当作普通类一样进行使用,但把它当JavaBean用肯定需要带来一些额外的好处,我们才会去了解和应用JavaBean

使用JavaBean好处如下:
      1Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作
      2,JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省

如果要你自己去通过getX方法来访问私有的X,可能有一定难度。用内省这套API操作JavaBean比用普通类的方式更方便。

 

2  简单的JavaBean内省操作

通过内省的方式对ReflectPoint对象中的成员变量进行读写操作。

 

PropertyDescriptor类:属性描述器,提供了读取属性值的方法、设置属性值的方法。

它的构造函数:PropertyDescriptor( propertyName, JavaBean.getClass());  

                            //构造函数的参数:属性名,和JavaBeanClass实例对象。

代码示例:

//PropertyDescriptor:属性描述器类,具有读取属性值和设置属性值的方法
import java.beans.PropertyDescriptor; 
import java.lang.reflect.Method;

public class JavaBeanDemo {
	public static void main(String[] args) throws Exception {
		BeanPoint bp = new BeanPoint(3,5);
		
		String propertyName = "x";  //属性名
		PropertyDescriptor pd1 = new PropertyDescriptor(propertyName, bp.getClass());
		Method readMethod = pd1.getReadMethod(); //获得读取属性值的方法
		Object retVal = readMethod.invoke(bp); //读取JavaBean对象bp上x属性的值
		System. out.println(retVal);
		//结果:3
		
		PropertyDescriptor pd2 = new PropertyDescriptor(propertyName, bp.getClass());
		Method writeMethod = pd2.getWriteMethod(); //获得设置属性值的方法
		Object value = 7;
		writeMethod.invoke(bp,value);  //设置x属性的值为7
		System. out.println(bp.getX());
		//结果:7
	}
}

class BeanPoint {
	private int x ;
	private int y ;
  
	public BeanPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	public int getX() {  //属性名:x
		return x ;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {  //属性名:y
		return y ;
	}
	public void setY(int y) {
		this.y = y;
	}
}

3  复杂的JavaBean内省操作

采用遍历JavaBean的所有属性的方式,来查找和设置JavaBeant对象的某个X属性。

1,在程序中把一个类当作JavaBean来看,

2,调用 Introspector.getBeanInfo方法,得到BeanInfo对象,

3,调用 BeanInfo对象的 getPropertyDescriptors方法,获取所有属性的属性描述器。

4,遍历每个属性描述器,若是想查找的属性,则设置。

BeanInfo对象封装了把这个类当作JavaBean看的结果信息。

 

见代码及注释:

import java.beans.*;
import java.lang.reflect.*;

public class JavaBeanDemo2 {
	public static void main(String[] args) throws Exception {
		BeanPoint bp = new BeanPoint(3, 5); //创建一个JavaBean
		
		String propertyName = "x";  //x属性
		Object retVal = getProperty(bp, propertyName); //获得bp中x属性的值
		System. out.println(retVal);
		
		Object value = 7;
		setProperty(bp, propertyName, value); //设置bp中x属性值为7.
		System. out.println(bp.getX());
	}
	
	//设置JavaBean对象bp中,propertyName属性的值为value。
	private static void setProperty(Object bp, String propertyName,Object value)
		throws Exception{
		
		//获得bp对应的JavaBean的BeanInfo,再通过BeanInfo获得所有属性的属性描述器。
		BeanInfo beanInfo = Introspector.getBeanInfo(bp.getClass());
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); //属性描述器
		for (PropertyDescriptor pd : pds){
			if (pd.getName().equals(propertyName)){  //获取属性名
			 Method writeMethod = pd.getWriteMethod();
			 writeMethod.invoke(bp,value);  //设置bp中属性propertyName的值为value
		   }
		}
	}
	
	//获得JavaBean对象bp中属性propertyName的值。
	private static Object getProperty(Object bp, String propertyName)
		throws Exception{
			  
		BeanInfo beanInfo = Introspector.getBeanInfo(bp.getClass());//获得BeanPoint的BeanInfo
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();//获取所有属性的属性描述器
		Object retVal = null ;
		for (PropertyDescriptor pd : pds){
			if (pd.getName().equals(propertyName)){  //如果是指定的属性
				Method readMethod = pd.getReadMethod();//就获取该属性的值
				retVal = readMethod.invoke(bp);
		    }
		}
		return retVal;
	}
}

class BeanPoint{
	private int x ;
	private int y ;
  
	public BeanPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	public int getX() {  //属性名:x
		return x ;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {  //属性名:y
		return y ;
	}
	public void setY(int y) {
		this.y = y;
	}
}


4  使用BeanUtils工具包操作JavaBean

使用BeanUtils工具包,首先导入要到如jar包:


因为beanutils工具包包依赖于logging包,还要继续导入logging包:


导入方法:如果在Eclipse开发环境下,把这两个jar包拷贝到工程根目录下的lib文件夹中,

然后右击该jar-->Build Path-->Add to Build Path

效果如下:

JavaBean内省:认识JavaBean与内省、对JavaBean的内省操作、Beanutils工具包_第1张图片

使用Beanutils工具包后,代码简化很多:

import org.apache.commons.beanutils.BeanUtils;

public class BeanUtils {
	public static void main(String[] args) throws Exception {
		BeanPoint bp = new BeanPoint(3, 5);
		
		//使用Beanutils工具包,获取bp中x属性的值。
		System.out.println(BeanUtils.getProperty(bp, "x"));
		
		//使用Beanutils工具包,设置bp中x属性的值为7.
		BeanUtils. setProperty(bp, "x", "7");
		System. out.println(bp.getX());
	}
}

注意:

1,BeanUtils工具类在对对象的属性进行操作的时候,会自动进行类型转换。

   例如BeanPoint类中的x属性为int类型,但是设置属性值的时候传入的参数却可以是String类型,这是因为内部发生了自动类型转换。

2,BeanUtils工具类可以对属性进行级联操作,

   例如Datejava.util.Date)类中有setTime方法,

   那么也就相当于Date类型对象有一个time属性,BeanUtils就可以对其进行操作:

   BeanUtils. setProperty(pt1, "birthday.time", "111"); // birthday.time,级联操作。

3,PropertyUtils类也可以操作对象的属性,但是与BeanUtils不同的是它不能进行自动类型转换。

   例如BeanPoint类中的x属性为int类型,但是设置属性值的时候传入的参数就不可以是String类型。



你可能感兴趣的:(Java基础)