一、内省
1、内省对应的英文单词为IntroSpector,英文意思是检查、视察、体检之意,对于程序即对内部进行检查,了解更多的底层细节。
2、内省的作用:主要针对JavaBean进行操作。
二、JavaBean
1、简述:
1)JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类中的方法主要用于访问私有的字段,且方法符合某种特殊的命名规则。
2)它是一种特殊的Java类,其中的方法符合特殊的规则。只要一个类中含有get或is和set打头的方法,就可以将其当做JavaBean使用。
3)字段和属性:
字段就是我们定义的一些成员变量,如private String name;等
JavaBean的属性是根据其中的setter和getter方法来确定的,而不是依据其中的变量,如方法名为setId,则中文意思是设置Id,getId也是如此;去掉set或者get前缀,剩余部分就是属性名称。如果剩余部分的第二个字母小写,则把剩余部分改为小写。如:getAge/setAge-->age;gettime-->time;setTime-->time;getCPU-->CPU。
总之,一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。
2、作用:
如果要在两个模板之间传递多个信息,可将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO),这些信息在类中用私有字段来储存,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。
3、JavaBean的好处:
一个符合JavaBean特点的类当做普通类一样可以使用,但是把它当做JavaBean类用会带来一些额外的好处:
1)在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作,别人都这么用和要求这么做,那你就没什么挑选的余地!
2)JDK中提供了对JavaBean进行操作的API,这套API称为内省,若要自己通过getX的方式来访问私有x,可用内省这套API,操作JavaBean要比使用普通的方式更方便。
示例:
package cn.itheima.demo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
importjava.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class IntroSpectorDemo {
publicstatic void main(String[] args) throws Exception {
HashCodeTesthct=new HashCodeTest(2,3);
StringpropertyName="x";
//"x"-->"X"-->"getX"-->MethodGetX-->
//用内省的方式
//获取并getX方法
Objectretval = getProperty1(hct, propertyName);
System.out.println(retval);
Objectvalue=5;
//获取并调用setX方法
setProperty(hct,propertyName, value);
System.out.println(hct.getX());
}
//获取并调用setX方法
privatestatic void setProperty(HashCodeTest hct, String propertyName,
Objectvalue) throws IntrospectionException,
IllegalAccessException,InvocationTargetException {
PropertyDescriptorpd=new PropertyDescriptor(propertyName,hct.getClass());//创建对象关联
MethodmethodSetX=pd.getWriteMethod();//获取JavaBean类中的setX方法
methodSetX.invoke(hct,value);//调用setX方法
}
//获取并getX方法
privatestatic Object getProperty1(HashCodeTest hct, String propertyName)
throwsIntrospectionException, IllegalAccessException,
InvocationTargetException{
PropertyDescriptorpd=new PropertyDescriptor(propertyName,hct.getClass());//创建对象关联
MethodmethodGetX=pd.getReadMethod();//获取JavaBean类中的getX方法
Objectretval=methodGetX.invoke(hct);//调用getX方法
returnretval;
}
}
Eclipse小技巧:
选择要变为方法的代码,右键——>Refactor——>ExtractMethod,然后就会生成一个方法了。
三、对JavaBean的复杂内省操作
1、在IntroSpector类中有getBeanInfo(Classcls)的方法,通过此方法获取BeanInfo实例。参数是相应对象的字节码,即Class对象。
2、BeanInfo类中有getPropertyDescriptors()的方法,可获取所有的JavaBean类中的属性信息,返回一个PropertyDescriptor[]。
3、在通过遍历的形式,获取与想要的那个属性信息。
如:获取并调用getX方法
//第二种较复杂的获取并调用JavaBean中的getX方法
private static ObjectgetProperty2(HashCodeTest hct, String propertyName)
throwsIntrospectionException, IllegalAccessException,
InvocationTargetException{
BeanInfobeanInfo=Introspector.getBeanInfo(hct.getClass());//创建对象关联
PropertyDescriptor[]pds=beanInfo.getPropertyDescriptors();//获取所有的属性描述
Objectretval=null;
//遍历
for(PropertyDescriptor pd : pds) {
//如果属性跟参数的属性相等,就获取它的getX方法
if(pd.getName().equals(propertyName)) {
MethodmethodGetX=pd.getReadMethod();//获取getX方法
retval=methodGetX.invoke(hct);
break;
}
}
returnretval;
}
四、BeanUtils工具包
1、BeanUtils等工具包都是由阿帕奇提供的,为了便于开发。
2、BeanUtils可以将8种基本数据类型进行自动的转换,因此对于非基本数据类型,就需要注册转换器Converter,这就需要ConverUtils包。
3、好处:
1)提供的set或get方法中,传入的是字符串,返回的还是字符串,因为在浏览器中,用户输入到文本框的都是以字符串的形式发送至服务器上的,所以操作的都是字符串。也就是说这个工具包的内部有自动将整数转换为字符串的操作。
2)支持属性的级联操作,即支持属性链。如可以设置:人的脑袋上的眼睛的眼珠的颜色。这种级联属性的属性连如果自己用反射,那就很困难了,通过这个工具包就可以轻松调用。
4、可以和Map集合进行相互转换:可将属性信息通过键值对的形式作为Map集合存储(通过staticjava.util.Mapdescribe(java.lang.Object bean)的方法)。也可以将Map集合转换为JavaBean中的属性信息(通过staticvoid populate(java.lang.Objectbean, java.util.Map properties)的方法)。
注:要正常使用BeanUtils工具,还要将Apache公司的logging(日志)的jar包也添加进BuildPath。
示例:
package cn.itheima.demo;
importorg.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
public class IntroSpectorDemo {
publicstatic void main(String[] args) throws Exception {
HashCodeTesthct=new HashCodeTest(2,3);
StringpropertyName="x";
//"x"-->"X"-->"getX"-->MethodGetX-->
//用BeanUtils工具包的方法
System.out.println(BeanUtils.getProperty(hct,propertyName));//get
BeanUtils.setProperty(hct,propertyName, "9");//set
System.out.println(hct.getX());
//对于JavaBean中的属性是对象的操作
BeanUtils.setProperty(hct,"birthday.time", "10");//set
System.out.println(BeanUtils.getProperty(hct,"birthday.time"));//get
}
}
5、BeanUtils工具包中还有一个工具类PropertyUtils,用法跟BeanUtils一样。区别:
1)BeanUtils会对JavaBean的属性的类型进行转换,如属性本身是integer,会转换为String。
2)PropertyUtils以属性本身的类型进行操作。
如:
//用BeanUtils工具包的工具类BeanUtils方法
BeanUtils.setProperty(hct,propertyName, "9");//set,9是String
System.out.println(BeanUtils.getProperty(hct,propertyName));//get
System.out.println(BeanUtils.getProperty(hct,propertyName).getClass().getName());//java.lang.String
//BeanUtils工具包中的PropertyUtils的操作
PropertyUtils.setProperty(hct,propertyName, 9);//9是Integer
System.out.println(PropertyUtils.getProperty(hct,propertyName));
System.out.println(PropertyUtils.getProperty(hct,propertyName).getClass().getName());//java.lang.Integer