You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 03:06:03