基础加强____【内省JavaBean】【BeanUtils框架】



"内省"(IntroSpector)--> 了解"JavaBean"
	"*"JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类的方法主要用于访问私有字段
		且其方法符合一定的命名规则: getXxx() setXxx(),可以通过方法名推断其功能
	"*"如果在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象
	(Value Object,简称VO)。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,
	则需要通过一些相应的方法来访问,JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。
	"*"可以吧javaBean 当做普通的类来使用,但JavaBean能够带来一些额外的好处
		首先,JavaBean是Java EE开发中的应用规范
		JDK提供了一些对JavaBean进行操作的API"内省",比按照普通的类操作更方便
	eclipse可以通过右键菜单source生成setter & getter方法	
	用内省的方式来读取JavaBean的属性

内省综合案例
	演示用eclipse自动生成ReflectPoint类 的setter & getter方法
	创建一个 PropertyDescriptor 对象来获取该属性的描述,对setter & getter进行重构
	用eclipse将读取属性和设置属性方法分别抽取成方法
		只要调用这个方法,并对这个方法传递一个 对象&属性名&设置值,就能完成属性修改的功能
		得到BeanInfo的方式 obj.getClass() 比 类名.class 更通用
	
相比较为复杂的方法(内省类)
	采用遍历BeanInfo的所有属性来查找和设置某个ReflectPoint对象的x属性,在程序中把一个类当做JavaBean来看待。
	调用 Introspector.getBeanInfo方法,得到BeanInfo对象,该对象封装了把这个类当做JavaBean的信息
	

"BeanUtils 框架"
	使用BeanUtils开源框架来操作JavaBean,BeanUtils框架非常有用
	首先将该框架的jar包导入到eclipse工程中
	下载BeanUtil包,将beanutils.jar文件copy到工程的lib目录下,将该目录添加路径buildpath-->addpath
	下载Logging包,添加jar
使用BeanUtils框架的好处: 
	(1)框架中集成了对对象进行操作的方法,可以直接使用不用再自己定义,接受的参数类型为String,避免了转数据类型的麻烦
	(2)可以接收"属性面",对复合属性逐级向下查找
		如birthday是Person的成员属性,Person中提供了相应的set & getBirthday方法
		同时birthday是一个Date类的实例对象,date类提供了setTim方法,就可以将Date类也当做JavaBean来看待
		通过修改time的属性来修改birthday,如果自己定义的话是比较繁琐的,而BeanUtil框架可以一步到位
			将要修改的参数设置为 birthday.time,就能直接对该属性进行设置
		BeanUtils.setProperty(pt1, "birthday.time", 6783);
	BeanUtils 比普通工具类强在对参数的处理上
	PropertyUtils.setProperty(pt1, "x", 88);//如 88 就不能改成字符串"88",而 BeanUtils 可以

附: 对象作为一个类中的成员存在时,如果不进行初始化,在调用该属性时会抛出空指针异常
	
java 7 的新特性, Map 定义方式
/*		Map[] map = {name:"asd" , age:22};
		BeanUtils.setProperty(map, name, age);
*/

代码实现

package itheima.enhance;

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 IntroSpector {
	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		
		ReflectPoint pt1 = new ReflectPoint(3, 5);
//用内省的方式来读取JavaBean的属性
		String propertyName = "x";	//属性名
	//普通方式:"x"-->"X"-->"getX"-->MethodGetX-->...
		
		//重构get方法
		Object retVal = getProperty(pt1, propertyName);
		System.out.println(retVal);
		//重构set
		Object value = 8;
		setProperty(pt1, propertyName, value);	
		System.out.println(pt1.getX());
		
//使用BeanUtil开源框架提供的set & get
		System.out.println(BeanUtils.getProperty(pt1, "x").getClass().getName());
	//(1)set.可以接收字符串,又可接收int
		BeanUtils.setProperty(pt1, "x", "22");	
		System.out.println(pt1.getX());
		
	//(2)使用BeanUtils的另一个好处,可以接收属性面,对复合属性进行操作
		// 如birthday是Person的成员属性,Person中提供了相应的setBirthday & getBirthday方法
		//同时是一个Date类的实例对象,date类提供了setTim方法,就可以将Date类也当做JavaBean来看待
		//通过修改time的属性来修改birthday
		BeanUtils.setProperty(pt1, "birthday.time", 6783);
		System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));
		
		//Java 7 新特性
/*		Map[] map = {name:"asd" , age:22};
		BeanUtils.setProperty(map, name, age);
*/		
		//如 88 就不能改成字符串"88",而 BeanUtils 可以
		PropertyUtils.setProperty(pt1, "x", 88);
		System.out.println(PropertyUtils.getProperty(pt1, "x"));
		
	}

	private static void setProperty(ReflectPoint pt1, String propertyName,
			Object value) throws IntrospectionException,
			IllegalAccessException, InvocationTargetException {
		PropertyDescriptor pd2 = new PropertyDescriptor(propertyName, pt1.getClass());
		//获得该属性的描述中写入(set)属性值的方法
		Method methodSetX = pd2.getWriteMethod();
		methodSetX.invoke(pt1,value);
	}

	private static Object getProperty(ReflectPoint pt1, String propertyName)
			throws IntrospectionException, IllegalAccessException,
			InvocationTargetException {
/*		//获取该JavaBean "x"属性方法的描述
		PropertyDescriptor pd = new PropertyDescriptor(propertyName, pt1.getClass());
		//获得应该用于(get)读取属性值的方法
		Method methodGetX = pd.getReadMethod();
		//通过获取的方法创建getX()方法的当前对象所对应的值
		Object retVal = methodGetX.invoke(pt1);
*/		
	//较为复杂的一种方法:调用 Introspector (内省)类的方法获取该类的 BeanInfo
		BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());
		//通过BeanInfo的方法获取该类所有属性的描述
		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;
	}

}




posted on 2014-02-13 14:24  hwren  阅读(184)  评论(0编辑  收藏  举报

导航