java内省机制基于反射封装,专用于javabean,通过getter/setter操作属性;需确保类public、有无参构造器,属性方法命名规范且类型匹配;读写前须判空方法,捕获并处理异常;获取beaninfo时应排除父类、注意缓存陷阱,推荐使用beanutils或beanwrapper简化开发。

Java内省机制专为JavaBean设计,本质是基于反射的封装,但它不直接操作字段,而是通过规范化的getter/setter方法来读写属性、响应事件。它让代码更简洁、更符合Bean约定,避免手写大量反射逻辑。
确认JavaBean是否合规
内省只对严格符合规范的类生效,否则PropertyDescriptor可能缺失getter或setter。检查以下三点:
- 类必须是public,且有无参构造器
- 每个属性必须有配套的public getter(如
getName())和setter(如setName(String)),命名需准确:属性名首字母小写,方法名对应驼峰大写(如属性userId→ getter为getUserId(),不是getUserid()) - setter返回类型必须是
void,且仅有一个参数;getter不能带参数,返回值类型须与属性一致
获取属性描述并安全读写值
使用Introspector.getBeanInfo()获取BeanInfo,再提取PropertyDescriptor数组。关键是要判空——因为某些属性可能只有getter(如计算属性),或setter被意外省略:
- 调用
pd.getReadMethod().invoke(obj)前,先判断pd.getReadMethod() != null - 调用
pd.getWriteMethod().invoke(obj, value)前,确保pd.getWriteMethod() != null,且传入参数类型匹配(如给int属性赋值,不能传String) - 捕获
IllegalAccessException和InvocationTargetException;后者需用e.getCause()查看原始异常(比如setter内部抛出的NullPointerException)
处理父类属性与缓存陷阱
默认Introspector.getBeanInfo(YourBean.class)会包含Object及其所有父类的属性(如toString方法也被当事件)。实际业务中通常只需本类属性:
- 传入第二个参数
Object.class:即getBeanInfo(YourBean.class, Object.class),排除Object以上层级 - 修改Bean后(如新增setter),
Introspector会缓存结果,导致旧信息仍被返回——开发或热部署时务必调用Introspector.flushCaches() - 生产环境慎用
flushCaches()频繁调用;若需动态更新,可改用Introspector.getBeanInfo(clazz, Introspector.USE_ALL_BEANINFO)绕过缓存(性能开销略高)
简化操作:优先考虑工具类封装
手动遍历PropertyDescriptor易出错且重复。实际项目中推荐:
- 用Apache Commons BeanUtils:
BeanUtils.getProperty(obj, "name")/BeanUtils.setProperty(obj, "age", 25),自动处理空值、类型转换和异常包装 - Spring的
BeanWrapper更强大,支持嵌套属性(如"address.city")、自定义编辑器和数据绑定 - 自己封装工具方法时,应内置
flushCaches()开关、类型安全检查和统一异常处理,而非裸用PropertyDescriptor.invoke()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











