"内省"(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;
}
}