java-内省机制

java-内省机制

起男 2 2025-02-05

java-内省机制

内省是指程序运行时检查对象类型的能力。在 Java 中,内省机制是一种用于处理符合 JavaBean 规范的类的方法。它提供了一套 API,允许我们通过程序化的方式访问和操作类的属性、方法及事件。通过这种方式,我们可以在不知道具体实现细节的情况下,动态地访问或修改对象的状态

内省和反射

  • 反射是一种更为通用的技术,指程序在运行时通过检查或“自检”其结构,动态修改自身行为的能力。通过反射,我们可以动态地加载类、创建对象实例、调用方法以及访问字段等,并且反射是可以应用于任何类的,无论该类是否遵循了 JavaBean 规范
  • 内省其实是基于反射实现的,只是提供了更高层次的抽象,它更专注于对 JavaBean 的操作,使得操作 JavaBean 更加方便高效。例如,当我们想要获取某个类的所有公共字段时,可以使用反射直接获取 Field 对象数组;但如果操作的目标符合 JavaBean 规范,则应该优先考虑使用内省机制

什么是JavaBean

JavaBean 是指符合特定规范的 Java 类,主要用于封装数据。成为一个 JavaBean 需要满足以下这几个条件:

  • 无参构造方法:必须有一个无参构造方法,确保可以通过默认构造器创建实例。
  • 私有化属性:所有属性须使用 private 访问修饰符封装,防止外部随意更改类的内部状态。
  • 提供公共的 getter 和 setter 方法:为每个属性定义相应的 public 读写方法,并遵循命名约定(如 getName()setName(String name))。
  • 序列化支持:实现 Serializable 接口,以保证对象能够序列化为字节流便于存储或者网络传输。

核心组件

Java 内省机制主要依赖于 java.beans 包下的几个关键类和接口

  • Introspector 类:内省机制的核心类,提供了静态方法 getBeanInfo(Class<?> beanClass) 来获取给定类型的 JavaBean 信息。该方法返回一个 BeanInfo 对象,对象中包含了关于此 JavaBean 的全面描述,包括所有属性、方法和事件等信息。

  • BeanInfo 接口:JavaBean 信息的顶层抽象,定义了如何描述一个 JavaBean 的行为,用于提供 JavaBean 的元数据。通过 BeanInfo,我们可以获取 Bean 的属性描述符(PropertyDescriptor[] getPropertyDescriptors())、方法描述符(MethodDescriptor[] getMethodDescriptors())以及其他相关信息。

  • PropertyDescriptor 类:对于 JavaBean 的每一个属性,都会有一个对应的 PropertyDescriptor 实例。该类不仅封装了属性的基本信息(如名称、类型),还提供了对 getter 和 setter 方法的访问途径。获取到 PropertyDescriptor 实例后,就可以实现 JavaBean 的属性值读写了。

DEMO

		UserDTO user = new UserDTO();
        user.setName("zhangsan");
		//查看所有属性和值
        BeanInfo beanInfo = Introspector.getBeanInfo(UserDTO.class);
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
            if ("class".equals(propertyDescriptor.getName()))
                continue;
            String name = propertyDescriptor.getName();
            Object value = propertyDescriptor.getReadMethod().invoke(user);
            System.out.println(name+":"+value);
        }
		//修改指定属性的值 注意:对set方法的名称和结构有强要求,如使用Lombok的@Accessors会报错
        PropertyDescriptor pd = new PropertyDescriptor("name",UserDTO.class);
        Method writeMethod = pd.getWriteMethod();
        writeMethod.invoke(user,"lisi");
		//查看指定属性的值
        Method readMethod = pd.getReadMethod();
        Object newValue = readMethod.invoke(user);
        System.out.println(newValue);