Java内省基于反射实现,专用于JavaBean的getter/setter访问;需严格遵循命名规范,使用PropertyDescriptor安全读写,并推荐Apache Commons BeanUtils或Spring BeanWrapper等成熟工具。

Java 反射是底层能力,内省是面向 JavaBean 的高层抽象——二者不是并列关系,而是内省基于反射实现,专用于规范化的 getter/setter 访问。直接用反射操作字段(Field)虽快但绕过封装;内省则严格依赖方法命名规则,更安全、更符合 Bean 合约。
确认 JavaBean 是否真正合规
内省不会校验字段是否存在,只认方法名。不合规的类会导致 PropertyDescriptor 缺失读/写方法,后续调用必抛空指针。必须检查:
- 类为
public,且含无参构造器 - 属性
userName对应的 getter 必须是getUserName()(不能是getusername()或getuser_name()),返回类型与属性一致 - setter 必须是
setUserName(String),返回void,且仅一个参数 - 布尔属性可用
isXxx()(如isActive()),但不能混用getActive()
用 Introspector 获取属性描述器
Introspector.getBeanInfo() 是入口,但默认包含父类(如 Object)的全部方法,造成干扰。应显式截断:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 只取当前类定义的属性:
getBeanInfo(YourBean.class, Object.class) - 开发中修改了 setter/getter 后,旧缓存仍生效 → 调用
Introspector.flushCaches()清理(生产环境慎用) - 若需动态更新又不想清全局缓存,可传
Introspector.USE_ALL_BEANINFO参数绕过缓存
通过 PropertyDescriptor 安全读写值
PropertyDescriptor 不执行操作,只提供 Method 引用,必须配合反射调用:
- 读值前判空:
if (pd.getReadMethod() != null) { pd.getReadMethod().invoke(obj); } - 写值前双重检查:
if (pd.getWriteMethod() != null && value.getClass().isAssignableFrom(pd.getPropertyType())) - 捕获
IllegalAccessException和InvocationTargetException;后者需用e.getCause()查原始异常(比如 setter 内部 NPE) - JavaBean 规范要求 getter/setter 为 public,一般无需
setAccessible(true)
优先使用成熟工具类封装
手动遍历 PropertyDescriptor 易漏判空、类型错配、异常处理不全。生产项目推荐:
-
Apache Commons BeanUtils:提供
PropertyUtils.setProperty(obj, "name", "Alice"),自动处理类型转换与空值 -
Spring BeanWrapper:底层即基于
PropertyDescriptor+ 缓存优化(CachedIntrospectionResults),支持嵌套路径("address.city") - 禁用 Spring 内省缓存(
spring.beaninfo.ignore=true)会显著拖慢 IOC 启动速度
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










