zoukankan      html  css  js  c++  java
  • Java内省机制

    Wiki上的解释:在计算机科学中,内省是指计算机程序在运行时(Run time)检查对象(Object)类型的一种能力,通常也可以称作运行时类型检查。 不应该将内省和反射混淆。相对于内省,反射更进一步,是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。

     内省和反射有什么区别?

            反射是在运行状态把Java类中的各种成分映射成相应的Java类,可以动态的获取所有的属性以及动态调用任意一个方法,强调的是运行状态。
            内省(IntroSpector)是Java 语言对 Bean 类属性、事件的一种缺省处理方法。 JavaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。如果在两个模块之间传递信息,可以将信息封装进JavaBean中,这种对象称为“值对象”(Value Object),或“VO”。方法比较少。这些信息储存在类的私有变量中,通过set()、get()获得。内省机制是通过反射来实现的,BeanInfo用来暴露一个bean的属性、方法和事件,以后我们就可以操纵该JavaBean的属性。

      在Java内省中,用到的基本上就是上述几个类。 通过BeanInfo这个类就可以获取到类中的方法和属性。例如类 A 中有属性 name, 那我们可以通过 getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这就是默认的规则。 Java 中提供了一套 API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则(但你最好还是要搞清楚),这些 API 存放于包 java.beans 中,一般的做法是通过类 Introspector 的 getBeanInfo方法 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法,这就是内省机制。


     代码测试:

      首先,声明一个Bean对象用于测试:

     1 package bean;
     2 
     3 public class UserBean {
     4     private int userId;
     5     private String userName;
     6     private String userPass;
     7 
     8     public int getUserId() {
     9         return userId;
    10     }
    11 
    12     public void setUserId(int userId) {
    13         this.userId = userId;
    14     }
    15 
    16     public String getUserName() {
    17         return userName;
    18     }
    19 
    20     public void setUserName(String userName) {
    21         this.userName = userName;
    22     }
    23 
    24     public String getUserPass() {
    25         return userPass;
    26     }
    27 
    28     public void setUserPass(String userPass) {
    29         this.userPass = userPass;
    30     }
    31 
    32 }
    View Code

      测试代码:

     1 package bean;
     2 
     3 import java.beans.BeanInfo;
     4 import java.beans.IntrospectionException;
     5 import java.beans.Introspector;
     6 import java.beans.PropertyDescriptor;
     7 import java.lang.reflect.InvocationTargetException;
     8 import java.lang.reflect.Method;
     9 
    10 import org.junit.*;
    11 
    12 public class Test {
    13     private UserBean user;
    14 
    15     @Before
    16     public void init() {
    17         user = new UserBean();
    18         user.setUserId(1);
    19         user.setUserName("anmin");
    20         user.setUserPass("root");
    21     }
    22 
    23     @org.junit.Test
    24     public void getBeanPropertyInfo()
    25             throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    26         // 获取User-BeanInfo对象:beanInfo是对一个Bean的描述,可以通过它取得Bean内部的信息
    27         /**
    28          * 获取User-BeanInfo对象 
    29          * 1、Introspector类 是一个工具类,提供了一系列取得BeanInfo的方法;
    30          * 2、BeanInfo接口,对一个JavaBean的描述,可以通过它取得Bean内部的信息; 
    31          * 3、PropertyDescriptor属性描述器类, 对一个Bean属性的描述,它提供了一系列对Bean属性进行操作的方法
    32          */
    33         BeanInfo userBeanInfo = Introspector.getBeanInfo(UserBean.class);
    34         PropertyDescriptor[] pds = userBeanInfo.getPropertyDescriptors();
    35         for (PropertyDescriptor pd : pds) {
    36             Method method = pd.getReadMethod();
    37             String methodName = method.getName();
    38             Object result = method.invoke(user);
    39             System.out.println(methodName + "-->" + result);
    40         }
    41     }
    42 
    43     @org.junit.Test
    44     public void getBeanPropertyByName() throws Exception {
    45         // 获取name属性的属性描述器
    46         PropertyDescriptor pd = new PropertyDescriptor("userName", user.getClass());
    47         // 得到name属性的getter方法
    48         Method readMethod = pd.getReadMethod();
    49         // 执行getter方法,获取返回值,即name属性的值
    50         String result = (String) readMethod.invoke(user);
    51         System.out.println("user.name" + "-->" + result);
    52         // 得到name属性的setter方法
    53         Method writeMethod = pd.getWriteMethod();
    54         // 执行setter方法,修改name属性的值
    55         writeMethod.invoke(user, "李四");
    56         System.out.println("user.name" + "-->" + user.getUserName());
    57     }
    58 }
    View Code

      测试结果:

    1 getClass-->class bean.UserBean
    2 getUserId-->1
    3 getUserName-->anmin
    4 getUserPass-->root
    5 user.name-->anmin
    6 user.name-->李四
    View Code

     Apache开发了一套简单、易用的API来操作Bean的属性——BeanUtils工具包。下载地址:commons-beanutils-1.9.3-bin.zip  commons-logging-1.2-bin.zip。两个为依赖包,都需要下载,一起使用。

  • 相关阅读:
    博客园
    未释放的已删除文件
    ssh连接缓慢
    剑指 Offer 38. 字符串的排列
    剑指 Offer 37. 序列化二叉树
    剑指 Offer 50. 第一个只出现一次的字符
    剑指 Offer 36. 二叉搜索树与双向链表
    剑指 Offer 35. 复杂链表的复制
    剑指 Offer 34. 二叉树中和为某一值的路径
    剑指 Offer 33. 二叉搜索树的后序遍历序列
  • 原文地址:https://www.cnblogs.com/ustc-anmin/p/10210657.html
Copyright © 2011-2022 走看看