写点什么

浅谈 Java 内省

  • 2024-12-19
    北京
  • 本文字数:2040 字

    阅读完需:约 7 分钟

作者:京东物流 王国泰

一、什么是内省

  • 讲内省,不得不说 Java Bean,Bean 在 Java 中是一种特殊的类,主要用于装载数据,数据会被存储在类的私有属性中,通常具有无参构造函数、可序列化、以及通过 getter 和 setter 方法来访问属性。内省是 Java Beans 规范的一部分,使用 java.beans 包中的类来实现,最常用的类是 Introspector。通过内省,你可以获取一个 Java Bean 的属性描述符(PropertyDescriptor)和方法描述符(MethodDescriptor)

二、内省常用 API

1、相关类

2、Introspector

2.1 核心功能

  • 用于获取 Bean 的整体信息,包括属性描述符、方法描述符和事件描述符等

2.2 核心方法

  • getBeanInfo


BeanInfo beanInfo = Introspector.getBeanInfo(Vehicle.class);
复制代码

3、BeanInfo

3.1 核心功能

  • 用于提供有关 Bean 的元数据,通常用于描述 Bean 的属性、事件和方法

3.2 核心方法

  • getPropertyDescriptors


PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
复制代码


  • getMethodDescriptors


MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();
复制代码


  • getEventSetDescriptors


EventSetDescriptor[] eventSetDescriptors = beanInfo.getEventSetDescriptors();
复制代码

4、PropertyDescriptor

4.1 核心功能

  • 用于描述 Bean 的属性,提供了对属性的详细描述,包括属性的名称、类型、读方法 getter、写方法 setter 等

4.2 核心方法

  • getName


PropertyDescriptor namePD = new PropertyDescriptor("name", Vehicle.class);String name = namePD.getName();
复制代码


  • getReadMethod


PropertyDescriptor namePD = new PropertyDescriptor("name", Vehicle.class);Method getter = namePD.getReadMethod();
String methodName = getter.getName();String vehicleName = (String) getter.invoke(new Vehicle());
复制代码


  • getWriteMethod


PropertyDescriptor namePD = new PropertyDescriptor("name", Vehicle.class);Method setter = namePD.getWriteMethod();
String methodName = setter.getName();setter.invoke(new Vehicle(), "JD0001");
复制代码

5、MethodDescriptor

5.1 核心功能

  • 用于描述一个方法的属性,提供了对方法的详细描述,包括方法的名称、参数类型、返回类型等

5.2 核心方法

  • getName


MethodDescriptor methodDescriptor = new MethodDescriptor(Vehicle.class.getMethod("setName", String.class));String name = methodDescriptor.getName();
复制代码


  • getMethod


MethodDescriptor methodDescriptor = new MethodDescriptor(Vehicle.class.getMethod("setName", String.class));Method method = methodDescriptor.getMethod();method.invoke(new Vehicle(), "JD0001");
复制代码

6、EventSetDescriptor

6.1 核心功能

  • 用于描述一个 Bean 能够触发的一组事件,提供了有关事件监听器类型、添加和移除监听器的方法以及事件通知方法的信息

6.2 核心方法

  • 不常用

三、内省常见使用场景

1、依赖注入

  • Spring 使用内省来分析类的构造函数、字段和方法,并自动注入依赖对象,可参考 BeanWrapperImpl,部分源码如下:


@Overridepublic PropertyDescriptor[] getPropertyDescriptors() {  return getCachedIntrospectionResults().getPropertyDescriptors();}
复制代码

2、对象拷贝

  • Spring BeanUtils 使用内省来复制对象的属性,可参考 BeanUtils,部分源码如下:


public static PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) throws BeansException {  return CachedIntrospectionResults.forClass(clazz).getPropertyDescriptors();}
复制代码

3、开发工具和 IDE

  • 开发工具和集成开发环境(IDE,如 IntelliJ IDEA)使用内省来提供代码补全、重构、调试等功能

四、内省优缺点

1、优点

  • 灵活性和可扩展性:允许在运行时动态地获取和操作对象的属性和方法

  • 简化开发工作:支持框架和工具的开发,能够自动处理对象的属性和方法

2、缺点

  • 性能开销:比直接调用方法或访问字段要慢,而且不当使用可能会导致内存泄漏或增加 GC 压力

  • 访问安全:绕过 Java 的访问控制机制,访问私有字段和方法,可能会带来安全隐患,特别是在处理敏感数据时

  • 类型安全:通常是基于字符串名称进行的(如方法名、属性名),在编译时无法检查其正确性,容易导致运行时错误

  • 可读性和可维护性:代码可读性差,增加调试难度

五、内省与反射的区别

1、用途

  • 内省主要用于 Java Bean 的属性操作,适合于标准化的 Bean 操作

  • 反射则是更通用的机制,可以操作类的所有成员,包括私有成员

2、实现

  • 内省是基于 Java Beans 规范的,使用 java.beans 包

  • 反射是 Java 语言的核心特性,使用 java.lang.reflect 包

3、性能

  • 内省通常比反射快,主要原因是内省使用了缓存机制,减少了权限检查,并且在设计上针对特定场景进行了优化

相关文献

发布于: 刚刚阅读数: 6
用户头像

拥抱技术,与开发者携手创造未来! 2018-11-20 加入

我们将持续为人工智能、大数据、云计算、物联网等相关领域的开发者,提供技术干货、行业技术内容、技术落地实践等文章内容。京东云开发者社区官方网站【https://developer.jdcloud.com/】,欢迎大家来玩

评论

发布
暂无评论
浅谈Java内省_京东科技开发者_InfoQ写作社区