Spring项目中不依赖Commons BeanUtils获取Bean属性值的替代方案
嘿,这个场景太常见了!既然不想引入Commons BeanUtils,Spring本身就提供了好几套原生方案来替代PropertyUtils.getProperty(entity, field),给你整理了几个最实用的:
BeanWrapper(最推荐,完全匹配需求) Spring的BeanWrapper是专门用于操作Bean属性的核心工具类,和Commons PropertyUtils的行为几乎一致,支持嵌套属性(比如user.address.city这种层级路径),还能自动处理类型转换,关键是它属于Spring核心包,不用加任何额外依赖。
代码示例:
import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; // 直接获取单个属性值,支持嵌套路径 Object propertyValue = new BeanWrapperImpl(entity).getPropertyValue(field);
如果要处理可能的异常(比如属性不存在),可以捕获InvalidPropertyException:
try { Object propertyValue = new BeanWrapperImpl(entity).getPropertyValue(field); } catch (InvalidPropertyException e) { // 处理属性不存在的情况 e.printStackTrace(); }
ReflectionUtils(底层反射方案) 如果你需要更底层的反射控制,Spring封装的ReflectionUtils比JDK原生反射更易用,它自动处理了私有字段的访问权限、异常包装等问题。不过这个方案不支持嵌套属性,适合简单的单个字段获取场景。
代码示例:
import org.springframework.util.ReflectionUtils; // 根据字段名查找字段 Field targetField = ReflectionUtils.findField(entity.getClass(), field); if (targetField != null) { ReflectionUtils.makeAccessible(targetField); // 开放私有字段的访问权限 Object propertyValue = targetField.get(entity); }
BeanUtils.describe()(批量属性场景) Spring的BeanUtils提供了describe()方法,可以一次性将Bean的所有属性(包括父类属性)转换为Map<String, Object>,之后你可以从Map中直接取对应字段的值。不过这个方法会遍历所有属性,效率不如BeanWrapper,而且同样不支持嵌套属性,适合需要批量获取多个属性的场景。
代码示例:
import org.springframework.beans.BeanUtils; try { Map<String, Object> propertyMap = BeanUtils.describe(entity); Object propertyValue = propertyMap.get(field); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { // 处理异常 e.printStackTrace(); }
总结一下:如果你的需求和原PropertyUtils.getProperty完全一致(尤其是需要支持嵌套属性),优先用BeanWrapper;如果只是简单获取单个字段,ReflectionUtils更轻量;批量属性操作可以考虑BeanUtils.describe()。
内容的提问来源于stack exchange,提问作者user_27

