• 内省与JavaBean


    概述

    JavaBean代表一类特殊的Java类,这种类主要用来存储和传递属性信息,JavaBean中的方法主要用于设置和获取这些私有属性,他们有一定的命名规则,我们可以把它们想象为一个侧重属性信息的类,如JSP中的表单信息打包一样,这些信息就可以封装在一个JavaBean对象中,通过一些特殊的方式来操作。

    Introspector,即为内省

    public class Introspector
    extends Object
    
    

    Introspector 类为通过工具学习有关受目标 Java Bean 支持的属性、事件和方法的知识提供了一个标准方法。

    简单说,Introspector就是一种操作JavaBean的标准方式

    JavaBean一些简单操作

    写一个Bean类用作测试

       1: public class Bean {
       2:     private String name;
       3:     private int age;
       4:     private int num;
       5:     private int score;
       6:     
       7:     public Bean(String name, int age, int num, int score) {
       8:         super();
       9:         this.name = name;
      10:         this.age = age;
      11:         this.num = num;
      12:         this.score = score;
      13:     }
      14:     public String getName() {
      15:         return name;
      16:     }
      17:     public void setName(String name) {
      18:         this.name = name;
      19:     }
      20:     public int getAge() {
      21:         return age;
      22:     }
      23:     public void setAge(int age) {
      24:         this.age = age;
      25:     }
      26:     public int getNum() {
      27:         return num;
      28:     }
      29:     public void setNum(int num) {
      30:         this.num = num;
      31:     }
      32:     public int getScore() {
      33:         return score;
      34:     }
      35:     public void setScore(int score) {
      36:         this.score = score;
      37:     }
      38: }

    实现set和get方法的简单操作

       1: public class BeanTest {
       2:  
       3:     /**
       4:      * @param args
       5:      */
       6:     public static void main(String[] args) {
       7:         
       8:         //获取对象
       9:         Bean b = new Bean("Shawn",12,1,97);
      10:         //获取类字节码文件
      11:         Class beanClass = Bean.class;    
      12:         //设置需要操作的属性名
      13:         String propertyName = "name";
      14:         
      15:         //调用set和get方法
      16:         System.out.println(getProperty(beanClass, b, propertyName, null));
      17:         setProperty(beanClass, b, propertyName, new Object[]{"Feng"});
      18:         System.out.println(getProperty(beanClass, b, propertyName, null));
      19:                 
      20:     }
      21:     //封装javabean的set方法
      22:     private static void setProperty(Class beanClass,Object obj,String propertyName,Object[] values){
      23:         try {
      24:             //获取属性描述符对象
      25:             PropertyDescriptor pd = new PropertyDescriptor(propertyName, beanClass);
      26:             //得到set方法对象
      27:             Method setMethod = pd.getWriteMethod();
      28:             //利用反射执行set方法
      29:             setMethod.invoke(obj, values);
      30:         } catch (IllegalArgumentException e) {
      31:             // TODO Auto-generated catch block
      32:             e.printStackTrace();
      33:         } catch (IntrospectionException e) {
      34:             // TODO Auto-generated catch block
      35:             e.printStackTrace();
      36:         } catch (IllegalAccessException e) {
      37:             // TODO Auto-generated catch block
      38:             e.printStackTrace();
      39:         } catch (InvocationTargetException e) {
      40:             // TODO Auto-generated catch block
      41:             e.printStackTrace();
      42:         }
      43:     }
      44:     //封装javabean的get方法
      45:     private static Object getProperty(Class beanClass,Object obj,String propertyName,Object[] args){
      46:         Object retVal = null;
      47:         try {
      48:             //获取属性描述符对象
      49:             PropertyDescriptor pd = new PropertyDescriptor(propertyName, beanClass);
      50:             //得到get方法对象
      51:             Method getMethod = pd.getReadMethod();
      52:             //利用反射执行get方法
      53:             retVal = getMethod.invoke(obj, args);
      54:         } catch (IllegalArgumentException e) {
      55:             // TODO Auto-generated catch block
      56:             e.printStackTrace();
      57:         } catch (IntrospectionException e) {
      58:             // TODO Auto-generated catch block
      59:             e.printStackTrace();
      60:         } catch (IllegalAccessException e) {
      61:             // TODO Auto-generated catch block
      62:             e.printStackTrace();
      63:         } catch (InvocationTargetException e) {
      64:             // TODO Auto-generated catch block
      65:             e.printStackTrace();
      66:         }
      67:         return retVal;
      68:     }
      69: }

    利用内省实现一些复杂操作

       1: public class BeanTest2 {
       2:  
       3:     /**
       4:      * @param args
       5:      * @throws IntrospectionException 
       6:      * @throws InvocationTargetException 
       7:      * @throws IllegalAccessException 
       8:      * @throws IllegalArgumentException 
       9:      */
      10:     public static void main(String[] args) throws IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
      11:         
      12:         //获取对象
      13:         Bean b = new Bean("Shawn",12,1,97);
      14:         //获取类字节码文件
      15:         Class beanClass = Bean.class;    
      16:         //设置需要操作的属性名
      17:         String propertyName = "name";
      18:         
      19:         //根据类字节码对象获取Bean信息
      20:         BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);
      21:         //利用内省获取所有的属性描述符
      22:         PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
      23:         //遍历所有的属性描述符,找到要操作的属性,进行操作
      24:         for(PropertyDescriptor pd : pds){
      25:             if(pd.getName().equals(propertyName)){
      26:                 Method setMethod = pd.getWriteMethod();
      27:                 Method getMethod = pd.getReadMethod();
      28:                 System.out.println(getMethod.invoke(b, null));
      29:                 setMethod.invoke(b, "Feng");
      30:                 System.out.println(getMethod.invoke(b, null));
      31:             }
      32:         }
      33:     }
      34: }

    BeanUtils工具包

    BeanUtils工具包是apach提供的一套非常方便的用于操作JavaBean的工具

    BeanUtil实现set和get方法

       1: public class BeanUtilTest {
       2:  
       3:     /**
       4:      * @param args
       5:      * @throws NoSuchMethodException 
       6:      * @throws InvocationTargetException 
       7:      * @throws IllegalAccessException 
       8:      */
       9:     public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
      10:         
      11:         //获取对象
      12:         Bean b = new Bean("Shawn",12,1,97);
      13:         //设置需要操作的属性名
      14:         String propertyName = "score";
      15:         
      16:         //利用BeanUtils获取属性值
      17:         System.out.println(BeanUtils.getProperty(b, propertyName));
      18:         //利用BeanUtils设置属性值
      19:         BeanUtils.setProperty(b, propertyName, "33");
      20:         System.out.println(BeanUtils.getProperty(b, propertyName));
      21:     }
      22: }

    我们可以看到,即便操作的是int型的属性,接收的仍然是字符串数据

    BeanUtils包中还提供一个类PropertyUtils,也具有setProperty与getProperty的方法,与BeanUtils不同的是,传入的参数不需要进行类型转换,也就是说,如果BeanUtils中的方法类型转换出了问题时,可以采用PropertyUtils中的方法,直接传入对应类型的参数,同样可以达到目的。

    同时,BeanUtils还支持属性的级联操作

    比如一个人内部有心脏,而心脏内部又有左心房和右心房,那么我们可以直接通过BeanUtils设置和获取心脏的内部属性

       1: public class Heart{
       2:     private String left;
       3:     private String right;
       4:     public String getLeft() {
       5:         return left;
       6:     }
       7:     public void setLeft(String left) {
       8:         this.left = left;
       9:     }
      10:     public String getRight() {
      11:         return right;
      12:     }
      13:     public void setRight(String right) {
      14:         this.right = right;
      15:     }
      16: }
       1: public class Person{
       2:     private Heart heart = new Heart();
       3:     private Date birthday;
       4:     public Date getBirthday() {
       5:         return birthday;
       6:     }
       7:     public void setBirthday(Date birthday) {
       8:         this.birthday = birthday;
       9:     }
      10:     public Heart getHeart() {
      11:         return heart;
      12:     }
      13:     public void setHeart(Heart heart) {
      14:         this.heart = heart;
      15:     }
      16: }
       1: public class BeanUtilsTest2 {
       2:  
       3:     /**
       4:      * @param args
       5:      * @throws NoSuchMethodException 
       6:      * @throws InvocationTargetException 
       7:      * @throws IllegalAccessException 
       8:      */
       9:     public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
      10:         // TODO Auto-generated method stub
      11:         Person p = new Person();
      12:         System.out.println(BeanUtils.getProperty(p, "heart.left"));
      13:         BeanUtils.setProperty(p, "heart.left", "lll");
      14:         System.out.println(BeanUtils.getProperty(p, "heart.left"));
      15:     }
      16: }

    还有一个重要的操作,BeanUtils可以将Map集合对象与JavaBean对象的对应属性内容进行转换

       1: public class BeanUtilsTest3 {
       2:  
       3:     /**
       4:      * @param args
       5:      * @throws InvocationTargetException 
       6:      * @throws IllegalAccessException 
       7:      * @throws NoSuchMethodException 
       8:      */
       9:     public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
      10:         
      11:         //将JavaBean的属性信息映射到一个Map集合中
      12:         Map map = new HashMap();
      13:         Bean b = new Bean("Shawn", 12, 14, 90);        
      14:         map = BeanUtils.describe(b);
      15:         System.out.println(map);
      16:         
      17:         //将map集合中的属性写入到JavaBean对象中
      18:         map = new HashMap();
      19:         map.put("name", "Feng");
      20:         map.put("score", 22);        
      21:         BeanUtils.populate(b, map);
      22:         System.out.println(b.toString());
      23:     }
      24: }

    以上三点便是BeanUtils最常用的一些操作和特点,可以看到,BeanUtils的操作非常方便快捷,现在已经很普及了

    JavaBean的命名规则

    由于JavaBean中只有set和get方法是对外可见的,所以JavaBean内部属性用什么名字并不重要,只要设置好方法名称即可

    一般规则是

    如果方法名称为setXxx和getXxx,那么表示propertyName全为小写xxx

    如果方法名称为setXXx或者setXXX,那么表示propertyName为对应的XXx以及XXX

    一般setXxx以及setXXX比较常见,一个代表普通的变量,一个代表具有特殊含义的变量

    所以我们写方法名称时尽量按照这个命名规则写,设置propertyName时使用相对应的名称即可

  • 相关阅读:
    DS博客作业08--课程总结
    DS博客作业07-----查找
    DS博客作业06--图
    DS博客作业05--树
    DS博客作业08--课程总结
    DS博客作业07--查找
    DS博客作业06--图
    DS博客作业05--树
    DS博客作业03--栈和队列
    DS博客作业02--线性表
  • 原文地址:https://www.cnblogs.com/ShawnWithSmallEyes/p/3461999.html
Copyright © 2020-2023  润新知