反射与 Bean 操作
This content is not available in your language yet.
反射模块是 Hutool “短 API”背后的复杂区域。ReflectUtil 负责类、字段、方法和构造器访问,BeanUtil 在此之上补充属性描述、Map/Bean 转换和字段拷贝。源码阅读关键是理解查找、访问和转换三个阶段没有完全合并。
先给答案:反射模块是 Hutool “短 API”背后的复杂区域
Section titled “先给答案:反射模块是 Hutool “短 API”背后的复杂区域”反射模块是 Hutool “短 API”背后的复杂区域。ReflectUtil 负责类、字段、方法和构造器访问,BeanUtil 在此之上补充属性描述、Map/Bean 转换和字段拷贝。源码阅读关键是理解查找、访问和转换三个阶段没有完全合并。 正文沿“反射调用路径 -> Bean 操作路径 -> 缓存与性能”展开:先确认入口和状态归属,再跟踪控制流或数据流的推进,最后落到对外可观察的结果。
主要失效边界集中在“反射工具不应直接暴露为外部输入驱动的任意调用器”这些场景。它们破坏的是容量、顺序、并发或生命周期前提;排查时应先确认状态是否仍由正确对象持有,再核对推进条件和清理路径。
反射调用路径
Section titled “反射调用路径”类名/实例/方法名 -> 找到 Method/Constructor/Field -> 参数类型匹配与可访问性处理 -> invoke / get / set -> 异常包装或结果转换按名称查找不是按名称唯一定位:重载方法需要结合参数数量、原始类型、包装类型、继承关系和可访问性。一个“能调用”的实现如果只取第一个同名方法,面对重载就会产生隐蔽错误。
Bean 操作路径
Section titled “Bean 操作路径”BeanUtil.copyProperties -> BeanInfo / PropertyDescriptor -> 源属性读取 -> 类型转换、忽略策略、编辑器 -> 目标属性写入字段直接访问与 getter/setter 访问的语义不同。Bean 工具应明确是否支持私有字段、是否调用 setter、是否复制 null、是否递归复制嵌套对象,以及异常发生时是跳过还是终止。
反射元数据查找可以缓存,但缓存 key 必须包含 Class、方法名、参数类型和必要的访问上下文;只按方法名缓存会破坏重载正确性。JDK 方法句柄、Lambda 或字节码生成可减少调用成本,但首次创建和访问权限检查仍有成本。
反射工具不应直接暴露为外部输入驱动的任意调用器。类名、方法名和字段名来自请求参数时,要使用白名单、包边界和参数校验;setAccessible 或模块开放也不等于授权。
面试锚点
- 为什么反射方法缓存不能只用方法名做 key?
- Bean 拷贝中 null 策略和类型转换策略为何要分开?
- 如何把通用 ReflectUtil 限制在安全的内部扩展点?