一、内省

        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