Spring Boot中如何通过自定义注解修改POJO指定字段的setter赋值逻辑
你的思路完全可行,不需要手动写重复setter,也不需要额外做setter方法的动态生成,因为你的POJO本身就是由Jackson负责反序列化的,直接在Jackson反序列化阶段处理注解逻辑即可,实现成本极低。
实现方案(Jackson原生支持,无额外依赖)
1. 保留自定义注解
你已经定义好的注解不需要修改:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface AppendQuestionMark { }
2. 实现Jackson反序列化属性处理器
通过Jackson的BeanDeserializerModifier拦截所有带@AppendQuestionMark注解的String类型字段,自定义其反序列化逻辑:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.introspect.BeanDescription; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import java.io.IOException; import java.util.List; public class AppendQuestionMarkDeserializerModifier extends BeanDeserializerModifier { @Override public List<BeanPropertyDefinition> updateProperties(DeserializationConfig config, BeanDescription beanDesc, List<BeanPropertyDefinition> propDefs) { for (int i = 0; i < propDefs.size(); i++) { BeanPropertyDefinition prop = propDefs.get(i); // 仅处理带目标注解的String类型字段 if (prop.getField() != null && prop.getField().getAnnotation(AppendQuestionMark.class) != null && prop.getRawType() == String.class) { BeanPropertyDefinition modifiedProp = prop.withDeserializer(new StdDeserializer<String>(String.class) { @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String value = p.getValueAsString(); // 空值不处理避免NPE return value == null ? null : value + "?"; } }); propDefs.set(i, modifiedProp); } } return propDefs; } }
3. 注册到Spring Boot全局Jackson配置
将自定义处理器注册到Spring Boot的ObjectMapper中,全局生效:
import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.module.SimpleModule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class JacksonCustomConfig { @Bean public Module appendQuestionMarkModule() { SimpleModule module = new SimpleModule(); module.setDeserializerModifier(new AppendQuestionMarkDeserializerModifier()); return module; } }
效果说明
后续只需要在需要追加问号的String字段上添加@AppendQuestionMark注解即可,Jackson反序列化时会自动完成后缀拼接,不需要编写任何额外的setter代码。
如果你的场景不止是Jackson反序列化,其他业务代码调用setter时也需要自动追加问号,再考虑基于注解处理器(APT)或者字节码增强框架(如Byte Buddy)动态生成带自定义逻辑的setter方法,否则上述方案完全满足需求,是最高效的实现方式。
内容的提问来源于stack exchange,提问作者Robert Strauch
相关产品推荐
相关产品推荐

