JavaBean内省

1、什么是JavaBean?

       JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。


       如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO)。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。


       JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。如果方法名为setId,中文意思即为“设置id”,至于你把它存到哪个变量上,则不用管。如果方法名为getId,中文意思即为“获取id”,至于你从哪个变量上取,也不用管。去掉set或者get前缀,剩余部分就是属性名。


注意:

     如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。

     如果剩余部分的第二个字母是大写的,则把剩余部分保持不变,保持大写。

例如:

     setId的属性名是:id

     isLast的属性名是:last

     setCPU的属性名是:CPU

     getUPS的属性名是:UPS

 

     总之,一个类被当作JavaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。


2、使用JavaBean的好处:

       一个符合JavaBean特点的类可以当作普通类一样进行使用,但是把它当作JavaBean来使用会带来以下一些额外的好处。

     ①、在Java EE开发中,经常要使用到JavaBean,很多环境都要去使用JavaBean方式进行操作。

     ②、JDK中提供了针对JavaBean进行操作的一些API,这套API就称为内省。如果自己通过getX方法来访问私有的X,会有一定的难度。而用内省这套API操作JavaBean  比用普通类的方式更方便。

 

3、对JavaBean的简单内省操作

需求:通过内省的方式对ReflectPoint类的对象中的成员变量进行读写操作。

代码示例:

ReflectPoint.java

package cn.itcast.day1;
 
public class ReflectPoint {
      private int x;
      private int y;
 
      public ReflectPoint(int x, int y) {
         super();
         this.x = x;
         this.y = y;
      }
  
      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;
      }
}

InstroSpectorTest.java

package cn.itcast.day1;
 
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
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";
         PropertyDescriptor pd1 = newPropertyDescriptor(propertyName, pt1.getClass());
         Method methodGetX = pd1.getReadMethod();
         Object retVal = methodGetX.invoke(pt1);
         System.out.println(retVal);    //结果:3
     
         PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass());
         Method methodSetX = pd2.getWriteMethod();
         methodSetX.invoke(pt1,7);
         System.out.println(pt1.getX());    //结果:7
      }
}

 

Eclipse中方法抽取:

   抽取步骤:右键点击需要被抽取的代码,选择Refactor(重构) → ExtractMethod(抽取方法) → 输入抽取之后的方法名 → 点击OK完成。



方法抽取完成之后的代码如下:

IntroSpectorTest.java

package cn.itcast.day1;
 
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
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";
      Object retVal = getProperty(pt1, propertyName);
      System.out.println(retVal);
     
      Object value = 7;
      setProperty(pt1,propertyName, value);
      System.out.println(pt1.getX());
   }
 
   private static void setProperty(Object pt1, String propertyName,Objectvalue) throws IntrospectionException,IllegalAccessException,InvocationTargetException {
      PropertyDescriptor pd2 = new PropertyDescriptor(propertyName, pt1.getClass());
      Method methodSetX = pd2.getWriteMethod();
      methodSetX.invoke(pt1,value);
   }
 
   private static Object getProperty(Object pt1, String propertyName) throws IntrospectionException,IllegalAccessException,InvocationTargetException{
      PropertyDescriptor pd1 = newPropertyDescriptor(propertyName, pt1.getClass());
      Method methodGetX = pd1.getReadMethod();
      Object retVal = methodGetX.invoke(pt1);
      return retVal;
   }
}

       注意:方法抽取完成之后,为了使抽取后的方法具备通用性,一定要将方法中的某些参数的类型改为Object,以便可以接收任何类型的参数。

 

4、对JavaBean的复杂内省操作

       采用遍历BeanInfo类的所有属性的方式来查找和设置某个ReflectPoint类的对象的x的属性。

       在程序中把一个类当作JavaBean来看,就是调用InstroSpector.getBeanInfo()方法,得到的BeanInfo对象封装了把这个类当作JavaBean看的结果信息。

 

代码示例:

IntroSpectorTest.java

package cn.itcast.day1;
 
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;
 
public class IntroSpectorTest {
       public static void main(String[] args) throws Exception {
         ReflectPoint pt1 = new ReflectPoint(3,5);
       
         String propertyName = "x";
         Object retVal = getProperty(pt1,propertyName);
         System.out.println(retVal);
       
         Object value = 7;
         setProperty(pt1, propertyName,value);
         System. out.println(pt1.getX());
       }
 
       private static void setProperty(Object pt1, String propertyName,Object value) throwsIntrospectionException,IllegalAccessException,InvocationTargetException {
         BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());
         PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
         for (PropertyDescriptor pd : pds){
                if (pd.getName().equals(propertyName)){
                     Method methodSetX = pd.getWriteMethod();
                     methodSetX.invoke(pt1,value);
               }
         }
      }
 
       private static Object getProperty(Object pt1,String propertyName) throws IntrospectionException,IllegalAccessException, InvocationTargetException {
         BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());
         PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
         Object retVal = null ;
         for (PropertyDescriptor pd : pds){
                if (pd.getName().equals(propertyName)){
                     Method methodGetX = pd.getReadMethod();
                     retVal = methodGetX.invoke(pt1);
               }
         }
         return retVal;
       }
}


5、使用BeanUtils工具包操作JavaBean

       要使用BeanUtils工具包,首先要到Apache的官网上去下载BeanUtils工具包(http://commons.apache.org/ ),下载完成之后解压,然后再导入到Eclipse的工程里面去。


选中当前工程,在当前工程下创建一个普通文件夹目录lib,然后将beanutils的jar包拷贝到lib目录中




拷贝过来之后就可以在Eclipse当中看到beanutils的jar包了。

 

接下来需要将刚刚拷贝过来的jar包添加到Build Path当中,右键点击该jar包,选择Build Path → Add toBuild Path


添加到Build Path之后会在左边列表栏上出现一个小瓶子的图标,表示该jar包已经添加成功了



当使用beanutils工具包中的方法来操作JavaBean的时候,会出现如下报错,原因是beanutils工具包依赖于logging包(此jar包也可以在Apache官网下载),因此也需要下载logging日志包并添加到当前工程当中去,步骤和添加beanutils工具包一样。

 

添加common-logging包到Eclipse工程当中,添加之后同意也需要添加到Build Path,步骤和添加beanutils到Build Path当中一样。




使用BeanUtils工具包可以很方便的实现对JavaBean对象中成员变量的获取和设置等操作。

代码示例:

IntroSpectorTest.java

package cn.itcast.day1;
 
import org.apache.commons.beanutils.BeanUtils;
 
public class IntroSpectorTest {
      public static void main(String[]args) throws Exception{
         ReflectPoint pt1 = new ReflectPoint(3,5);
     
         System.out.println(BeanUtils.getProperty(pt1,"x"));
         //结果:7
         BeanUtils.setProperty(pt1,"x", "9");
         System.out.println(pt1.getX());
         //结果:9
      }
}

注意:

①、BeanUtils工具类在对对象的属性进行操作的时候,会自动进行类型转换。

       例如:ReflectPoint类中的变量xint类型,但是设置属性值的时候传入的参数却可以是String类型,这时因为它内部发生了自动类型转换。(示例如上)

②、BeanUtils工具类可以对属性进行级联操作。

       例如:Date类中有一个setTime()方法,那么也就相当于Date类型对象有一个名为time属性,BeanUtils工具类就可以对其进行操作。(示例如下)

 

代码示例:

ReflectPoint.java

package cn.itcast.day1;
 
import java.util.Date;
 
public class ReflectPoint {
      private Date birthday = newDate();
      public Date getBirthday() {
         return birthday;
      }
      public void setBirthday(Date birthday){
         this.birthday = birthday;
      }
 
      private int x;
      public int y;
      public ReflectPoint(int x, int y) {
         super();
         this.x = x;
         this.y = y;
      }
 
      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;
      }
}

IntroSpectorTest.java

package cn.itcast.day1;

importorg.apache.commons.beanutils.BeanUtils;

public class IntroSpectorTest {
       public static void main(String[] args) throws Exception {
           ReflectPoint pt1 = new ReflectPoint(3, 5);
       
           BeanUtils.setProperty(pt1,"birthday.time", "111");
           System.out.println(BeanUtils.getProperty(pt1,"birthday.time"));  //结果:111
       }
}

③、PropertyUtils类也可以操作对象的属性,但是与BeanUtils不同的是它不能进行自动类型转换。

       例如:ReflectPoint类中的变量x属性为int类型,但是设置属性值的时候传入的参数类型却不能为String类型。

 

代码示例:

package cn.itcast.day1;

import org.apache.commons.beanutils.PropertyUtils;

public class IntroSpectorTest {
       public static void main(String[] args) throws Exception {
         ReflectPoint pt1 = new ReflectPoint(3,5);
       
         PropertyUtils.setProperty(pt1,"x", "9");     //会报错。
         System.out.println(PropertyUtils.getProperty(pt1,"x").getClass());
       }
}


运行时会出现如下报错信息:

Exception in thread"main"java.lang.IllegalArgumentException: Cannot invoke cn.itcast.day1.ReflectPoint.setX on beanclass 'class cn.itcast.day1.ReflectPoint' - argument type mismatch - hadobjects of type "java.lang.String" but expected signature"int"

atorg.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:2181)

atorg.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:2097)

atorg.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1903)

atorg.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:2010)

atorg.apache.commons.beanutils.PropertyUtils.setProperty(PropertyUtils.java:896)

atcn.itcast.day1.IntroSpectorTest.main(IntroSpectorTest.java:39)

Caused by: java.lang.IllegalArgumentException: argument type mismatch

atsun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

atsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

atsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

atjava.lang.reflect.Method.invoke(Method.java:597)

atorg.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:2116)

... 5 more

 

处理方式:

需要将PropertyUtils.setProperty(pt1,"x", "9");中的属性值"9"改成int型的数值。

 

代码如下:

package cn.itcast.day1;

import org.apache.commons.beanutils.PropertyUtils;

public class IntroSpectorTest {
       public static void main(String[] args) throws Exception {
        ReflectPoint pt1 = new ReflectPoint(3, 5);
       
         PropertyUtils.setProperty(pt1,"x", 9);     //改为int型之后恢复正常。
         System.out.println(PropertyUtils.getProperty(pt1,"x").getClass());
       }
}


 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值