Java中如何对POJO所有带指定注解的字段统一应用过滤器修改值
最优实现方案
你遇到的栈溢出基本是递归处理嵌套POJO时碰到了循环引用(比如Pojo实例持有SubPojo,SubPojo实例又反向持有外层Pojo),或者没有限制递归边界导致的无限递归。
核心实现思路
- 引入已访问对象集合,基于对象引用判断是否已经处理过,避免循环递归
- 字段处理分两类:符合要求的
@AnnotatedProp注解String字段直接执行过滤逻辑,自定义POJO类型字段递归处理 - 增加类型判断边界,基础类型、包装类型、枚举等无需递归的类型直接跳过
代码实现
import java.lang.reflect.Field; import java.util.IdentityHashMap; import java.util.Set; // 过滤逻辑抽为函数式接口方便扩展 @FunctionalInterface interface StringFilter { String apply(String origin); } public class AnnotatedPropProcessor { public static void processPojo(Object obj, StringFilter filter) { // 基于对象引用判断已访问对象,避免值相同的不同对象被误判 Set<Object> visited = Set.newInstanceFrom(new IdentityHashMap<>()); doProcess(obj, filter, visited); } private static void doProcess(Object obj, StringFilter filter, Set<Object> visited) { if (obj == null || visited.contains(obj)) { return; } visited.add(obj); // 遍历当前类所有声明字段,包括private修饰的字段 Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); try { // 处理带@AnnotatedProp注解的String类型字段 if (field.getType() == String.class && field.isAnnotationPresent(AnnotatedProp.class)) { String originValue = (String) field.get(obj); if (originValue != null) { String newValue = filter.apply(originValue); field.set(obj, newValue); } continue; } // 跳过无需递归的类型:基础类型、枚举、数组、JDK自带类型(String、集合、包装类等) Class<?> fieldType = field.getType(); if (fieldType.isPrimitive() || fieldType.isEnum() || fieldType.isArray() || fieldType.getName().startsWith("java.") ) { continue; } // 递归处理自定义POJO类型字段 Object fieldValue = field.get(obj); doProcess(fieldValue, filter, visited); // 如需处理List<SubPojo>这类集合类型的嵌套POJO,可放开下面的扩展逻辑 /* if (fieldValue instanceof Iterable<?> iterable) { for (Object item : iterable) { doProcess(item, filter, visited); } } */ } catch (IllegalAccessException e) { // 按需调整异常处理逻辑 throw new RuntimeException("字段处理失败", e); } } } }
使用示例
// 示例过滤逻辑:把字段值中的"敏感词"替换为* Pojo pojo = new Pojo(); // 给pojo属性赋值逻辑... AnnotatedPropProcessor.processPojo(pojo, originStr -> originStr.replace("敏感词", "*"));
可选优化点
- 可对类的字段信息做本地缓存,避免每次处理对象都重新反射获取字段,大幅提升批量处理的性能
- 可按需扩展对Map、数组等其他容器类型的处理逻辑
内容的提问来源于stack exchange,提问作者Alexander Widera
相关产品推荐
相关产品推荐

