黑马程序员---JavaBean、內省以及第三方工具包BeanUtils的学习

------- android培训java培训、期待与您交流! ----------

 

 内省:introSpector   内省;自省;反省;在内心省察自己;胃镜检查;(intro:介绍,简介)

它主要用于被 JavaBean 进行操作。

什么是 JavaBean

JavaBean 是一种特殊的 Java 类,主要用于传递数据信息,这种 java 类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。
如果要在两个模块之间传递多个信息,可以将这些信息封装到一个 JavaBean 中,这种 JavaBean 的实例对象通常称之为值对象( Value Object ,简称 VO )。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问,大家觉得这些方法的名称叫什么好呢? JavaBean 的属性是根据其中的 setter getter 方法来确定的,而不是根据其中的成员变量。如果方法名为 setId ,中文意思即为设置 id ,至于你把它存到哪个变量上,用管吗?如果方法名为 getId ,中文意思即为获取 id ,至于你从哪个变量上取,用管吗?去掉 set 前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。

Class Person

{

            private int age;

            public int getAge()

            {

                       return age;

            }

            public void setAge(int age)

            {

                       this.age = age;

            }

}

Ø 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 比用普通类的方式更方便。

java.beans
PropertyDescriptor

PropertyDescriptor 描述 Java Bean 通过一对存储器方法导出的一个属性。属性描述符

构造方法摘要
PropertyDescriptor(String propertyName,Class<?> beanClass)
          通过调用 getFoo 和 setFoo 存取方法,为符合标准 Java 约定的属性构造一个 PropertyDescriptor。

 

 MethodgetReadMethod()
          获得应该用于读取属性值的方法。
 MethodgetWriteMethod()
          获得应该用于写入属性值的方法。

 JavaBean的简单应用方式

package cn.itcast.day1;

public class ReflectPoint {
	private int x;
	public int y;
	private String str1;
	public String str2;
	public String str3;
	
	public ReflectPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}

	public ReflectPoint(int x, int y, String str1, String str2, String str3) {
		super();
		this.x = x;
		this.y = y;
		this.str1 = str1;
		this.str2 = str2;
		this.str3 = str3;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ReflectPoint other = (ReflectPoint) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}

	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 toString() {
		return x + "::" + y + "::" + str1 + "::" + str2 + "::" + str3;
	}
}


package cn.itcast.day1;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

public class IntroSpectorTest {

	public static void main(String[] args) throws Exception {
		ReflectPoint pt1 = new ReflectPoint(3,5);
		String propertyName = "x";
		// x --> X --> getX() --> methodGetX -->
		//获得“x”的值,用内省的方式做:
		/*PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());
		Method methodGetX = pd.getReadMethod();
		Object retVal = methodGetX.invoke(pt1);*/
		Object retVal = getProperty(pt1,propertyName);
		System.out.println(retVal);//3
		
		//设置pt1的属性“x”的值:
		/*PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass());
		Method methodSetX = pd2.getWriteMethod();
		methodSetX.invoke(pt1, 7);*/
		setProperty(pt1,propertyName,7);
		System.out.println(pt1.getX());//将新值打印:7
	}
	
	private static Object getProperty(Object obj, String propertyName)  throws Exception {
		PropertyDescriptor pd = new PropertyDescriptor(propertyName, obj.getClass());
		Method methodGet = pd.getReadMethod();
		Object reVal = methodGet.invoke(obj);
		return reVal;
	}
	
	private static void setProperty( Object obj, String propertyName, Object Val) throws Exception {
		PropertyDescriptor pd = new PropertyDescriptor(propertyName,obj.getClass());
		Method methodSet = pd.getWriteMethod();
		methodSet.invoke(obj, Val);	
	}
}

 

对JavaBean的复杂内省操作

 java.beans
Introspector

static BeanInfogetBeanInfo(Class<?> beanClass)
          在 Java Bean 上进行内省,了解其所有属性、公开的方法和事件。
static BeanInfogetBeanInfo(Class<?> beanClass,Class<?> stopClass)
          在给定的“断”点之下,在 Java Bean 上进行内省,了解其所有属性和公开的方法。
static BeanInfogetBeanInfo(Class<?> beanClass, int flags)
          在 Java Bean 上进行内省,了解其所有属性、公开的方法和事件,并将结果用一些控制标记表示。

 得到BeanInfo对象,这个BeanInfo对象就代表了整个JavaBean。BeanInfo就代表了把一个对象当做JavaBean来看的结果。

Ø得到BeanInfo最好采用“obj.getClass()”方式,而不要采用“类名.class”方式,这样程序更通用。

采用遍历BeanInfo的所有属性方式来查找和设置某个RefectPoint对象的x属性。在程序中把一个类当作JavaBean来看,就是调用IntroSpector.getBeanInfo方法,得到的BeanInfo对象封装了把这个类当作JavaBean看的结果信息。

package cn.itcast.day1;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

public class IntroSpectorTest {

	public static void main(String[] args) throws Exception {
		ReflectPoint pt1 = new ReflectPoint(3,5);
		String propertyName = "x";
		// x --> X --> getX() --> methodGetX -->
		//获得“x”的值,用内省的方式做:
		Object retVal = getProperty(pt1,propertyName);
		System.out.println(retVal);//3
		
		//设置pt1的属性“x”的值:
		setProperty(pt1,propertyName,7);
		System.out.println(pt1.getX());//将新值打印:7
	}
	
	private static Object getProperty(Object obj, String propertyName)  throws Exception {
		Object retVal = null;
		BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
		for(PropertyDescriptor pd : pds) {
			if(pd.getName().equals(propertyName)) {
				Method methodGet = pd.getReadMethod();
				retVal = methodGet.invoke(obj);
				break;
			}
		}
		return retVal;
	}
	
	private static void setProperty( Object obj, String propertyName, Object Val) throws Exception {	
		BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
		for(PropertyDescriptor pd : pds) {
			if(pd.getName().equals(propertyName)) {
				Method methodSet = pd.getWriteMethod();
				methodSet.invoke(obj, Val);
				break;
			}			
		}		
	}
}

 

Beanutils工具包

在阿帕奇官网下载BeanUtils工具包: http://commons.apache.org/proper/commons-beanutils/download_beanutils.cgi

下载后解压缩,在 commons-beanutils-1.9.1\apidocs 文件夹下打开 index.html 查看这个工具包的API说明文档:

我们将 commons-beanutils-1.9.1.jar 拷贝到我们的项目文件夹下的lib包中,再点击右键选择BuildPath-->add BuildPath。

现在我们用org.apache.commons.beanutils 包下,的 Class BeanUtils的方法来获取某个类中某属性的值:
static StringgetProperty(Object bean,String name)
Return the value of the specified property of the specified bean, no matter which property reference format is used, as a String.
package cn.itcast.day1;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

import org.apache.commons.beanutils.BeanUtils;

public class IntroSpectorTest {

	public static void main(String[] args) throws Exception {
		ReflectPoint pt1 = new ReflectPoint(3,5);
		String propertyName = "x";
		// x --> X --> getX() --> methodGetX -->
		//获得“x”的值,用内省的方式做:
		/*PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());
		Method methodGetX = pd.getReadMethod();
		Object retVal = methodGetX.invoke(pt1);*/
		Object retVal = getProperty(pt1,propertyName);
		System.out.println(retVal);//3
		
		//设置pt1的属性“x”的值:
		/*PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass());
		Method methodSetX = pd2.getWriteMethod();
		methodSetX.invoke(pt1, 7);*/
		setProperty(pt1,propertyName,7);
		System.out.println(BeanUtils.getProperty(pt1, propertyName));//用导入第三方工具包BeanUtils的方法获取pt1类中属性“x”的值。
		System.out.println(pt1.getX());//将新值打印:7
	}
	
	private static Object getProperty(Object obj, String propertyName)  throws Exception {
		/*PropertyDescriptor pd = new PropertyDescriptor(propertyName, obj.getClass());
		Method methodGet = pd.getReadMethod();
		Object retVal = methodGet.invoke(obj);*/
		Object retVal = null;
		BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
		for(PropertyDescriptor pd : pds) {
			if(pd.getName().equals(propertyName)) {
				Method methodGet = pd.getReadMethod();
				retVal = methodGet.invoke(obj);
				break;
			}
		}
		return retVal;
	}
	
	private static void setProperty( Object obj, String propertyName, Object Val) throws Exception {
		/*PropertyDescriptor pd = new PropertyDescriptor(propertyName,obj.getClass());
		Method methodSet = pd.getWriteMethod();
		methodSet.invoke(obj, Val);*/	
		BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
		for(PropertyDescriptor pd : pds) {
			if(pd.getName().equals(propertyName)) {
				Method methodSet = pd.getWriteMethod();
				methodSet.invoke(obj, Val);
				break;
			}			
		}		
	}
}

但是我们发现没有第三方的logging会报错,于是我们再从官网下载Commons Logging

网站:http://commons.apache.org/proper/commons-logging/download_logging.cgi
下载之后解压,我们将commons-logging-1.1.3.jar文件也拷贝到项目中的lib文件夹下,并在右键Build Path子菜单中add。

add之后就会出现奶瓶状的图标:

这下就成功运行了。接下来我们还要去设置它的值:

static voidsetProperty(Object bean,String name,Object value)
Set the specified property value, performing type conversions as required to conform to the type of the destination property.

package cn.itcast.day1;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

import org.apache.commons.beanutils.BeanUtils;

public class IntroSpectorTest {

	public static void main(String[] args) throws Exception {
		ReflectPoint pt1 = new ReflectPoint(3,5);
		String propertyName = "x";
		// x --> X --> getX() --> methodGetX -->
		//获得“x”的值,用内省的方式做:
		/*PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());
		Method methodGetX = pd.getReadMethod();
		Object retVal = methodGetX.invoke(pt1);*/
		Object retVal = getProperty(pt1,propertyName);
		System.out.println(retVal);//3
		
		//设置pt1的属性“x”的值:
		/*PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass());
		Method methodSetX = pd2.getWriteMethod();
		methodSetX.invoke(pt1, 7);*/
		setProperty(pt1,propertyName,7);
		System.out.println(BeanUtils.getProperty(pt1, propertyName));//用导入第三方工具包BeanUtils的方法获取pt1类中属性“x”的值。
		BeanUtils.setProperty(pt1, propertyName, 9);//用导入的第三方工具包BeanUtils中的方法设置pt1类中属性“x”的值为9。
		System.out.println(pt1.getX());//将新值打印
	}
	
	private static Object getProperty(Object obj, String propertyName)  throws Exception {
		/*PropertyDescriptor pd = new PropertyDescriptor(propertyName, obj.getClass());
		Method methodGet = pd.getReadMethod();
		Object retVal = methodGet.invoke(obj);*/
		Object retVal = null;
		BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
		for(PropertyDescriptor pd : pds) {
			if(pd.getName().equals(propertyName)) {
				Method methodGet = pd.getReadMethod();
				retVal = methodGet.invoke(obj);
				break;
			}
		}
		return retVal;
	}
	
	private static void setProperty( Object obj, String propertyName, Object Val) throws Exception {
		/*PropertyDescriptor pd = new PropertyDescriptor(propertyName,obj.getClass());
		Method methodSet = pd.getWriteMethod();
		methodSet.invoke(obj, Val);*/	
		BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
		for(PropertyDescriptor pd : pds) {
			if(pd.getName().equals(propertyName)) {
				Method methodSet = pd.getWriteMethod();
				methodSet.invoke(obj, Val);
				break;
			}			
		}		
	}
}


在ReflectPoint类中加入Date类型的birthday属性,并为其添加get和set方法:

package cn.itcast.day1;

import java.util.Date;

public class ReflectPoint {
	private Date birthday = new Date();
	
	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	private int x;
	public int y;
	private String str1;
	public String str2;
	public String str3;
	
	public ReflectPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}

	public ReflectPoint(int x, int y, String str1, String str2, String str3) {
		super();
		this.x = x;
		this.y = y;
		this.str1 = str1;
		this.str2 = str2;
		this.str3 = str3;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ReflectPoint other = (ReflectPoint) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}

	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 toString() {
		return x + "::" + y + "::" + str1 + "::" + str2 + "::" + str3;
	}
}


Date类中有setTime()方法,所以也可以把Date类看成是JavaBean,得出Date类一定有一个time属性:

 voidsetTime(long time)
          设置此 Date 对象,以表示 1970 年 1 月 1 日 00:00:00 GMT 以后 time 毫秒的时间点。

birthday这个属性是一个复合属性,不是一个基本属性,它本身是一个对象,它也有自己的属性。

我们为pt1这个对象的birthday属性中的time属性赋值:

package cn.itcast.day1;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

public class IntroSpectorTest {

	public static void main(String[] args) throws Exception {
		ReflectPoint pt1 = new ReflectPoint(3,5);
		String propertyName = "x";
		// x --> X --> getX() --> methodGetX -->
		//获得“x”的值,用内省的方式做:
		/*PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());
		Method methodGetX = pd.getReadMethod();
		Object retVal = methodGetX.invoke(pt1);*/
		Object retVal = getProperty(pt1,propertyName);
		System.out.println(retVal);//3
		
		//设置pt1的属性“x”的值:
		/*PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass());
		Method methodSetX = pd2.getWriteMethod();
		methodSetX.invoke(pt1, 7);*/
		setProperty(pt1,propertyName,7);
		System.out.println(BeanUtils.getProperty(pt1, propertyName));//用导入第三方工具包BeanUtils的方法获取pt1类中属性“x”的值。
		BeanUtils.setProperty(pt1, propertyName, 9);//用导入的第三方工具包BeanUtils中的方法设置pt1类中属性“x”的值为9。
		System.out.println(pt1.getX());//将新值打印
		
		BeanUtils.setProperty(pt1, "birthday.time", 111);
		System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));		
	}
	
	private static Object getProperty(Object obj, String propertyName)  throws Exception {
		/*PropertyDescriptor pd = new PropertyDescriptor(propertyName, obj.getClass());
		Method methodGet = pd.getReadMethod();
		Object retVal = methodGet.invoke(obj);*/
		Object retVal = null;
		BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
		for(PropertyDescriptor pd : pds) {
			if(pd.getName().equals(propertyName)) {
				Method methodGet = pd.getReadMethod();
				retVal = methodGet.invoke(obj);
				break;
			}
		}
		return retVal;
	}
	
	private static void setProperty( Object obj, String propertyName, Object Val) throws Exception {
		/*PropertyDescriptor pd = new PropertyDescriptor(propertyName,obj.getClass());
		Method methodSet = pd.getWriteMethod();
		methodSet.invoke(obj, Val);*/	
		BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
		for(PropertyDescriptor pd : pds) {
			if(pd.getName().equals(propertyName)) {
				Method methodSet = pd.getWriteMethod();
				methodSet.invoke(obj, Val);
				break;
			}			
		}		
	}
}

BeanUtils类中还有将一个属性的值从一个JavaBean对象身上拷贝到另一个JavaBean对象身上的相同属性名的属性身上:

static voidcopyProperties(Object dest,Object orig)
Copy property values from the origin bean to the destination bean for all cases where the property names are the same.
static voidcopyProperty(Object bean,String name,Object value)
Copy the specified property value to the specified destination bean, performing any type conversion that is required.
还包含将一个javaBean对象转换为map集合的方法:

static Map<String,String>describe(Object bean)
Return the entire set of properties for which the specified bean provides a read method.

相反,也提供了方法将map集合的内容填充到一个JavaBean对象里面去:

static voidpopulate(Object bean,Map<String,? extendsObject> properties)
Populate the JavaBeans properties of the specified bean, based on the specified name/value pairs.

jdk1.7新特性:定义Map的方法:????????????????????????

org.apache.commons.beanutils包中还有一个类:Class PropertyUtils
这个类里面也有setProperty和getProperty方法:
static ObjectgetProperty(Object bean,String name)
Return the value of the specified property of the specified bean, no matter which property reference format is used, with no type conversions.

static voidsetProperty(Object bean,String name,Object value)
Set the value of the specified property of the specified bean, no matter which property reference format is used, with no type conversions.

它与BeanUtils的区别在于:BeanUtils是对属性的值以字符串形式操作的,传值的时候传字符串,返回也返回字符串。而PropertyUtils是对属性的值以属性本身的类型操作的,传值的时候传值本身的类型。


---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值