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

Spring Cache(Redis实现)序列化带@Validated的配置类问题

解决Spring Cache序列化含@Validated的ConfigurationProperties类问题

这个问题我之前也碰到过,核心原因是**@Validated注解会让Spring为MyProps生成一个AOP代理对象**(通常是CGLIB代理),而这个代理类默认没有正确实现Serializable接口,或者在序列化/反序列化过程中,代理的额外逻辑会导致失败——毕竟你的ClassThatNeedsToBeSerialized持有这个代理后的MyProps实例,序列化它的时候自然会出问题。

下面给你几个可行的解决方案,按推荐程度排序:

方案一:移除类上的@Validated,改用手动校验

这是最稳妥的方式,避免代理生成带来的序列化问题。我们可以在启动时手动绑定并校验MyProps,而不是依赖@Validated的AOP增强:

@Configuration
public class MyPropsConfig {
    @Bean
    @ConfigurationProperties(prefix = "myprops")
    public MyProps myProps(Validator validator) {
        MyProps props = new MyProps();
        // 手动触发校验
        Set<ConstraintViolation<MyProps>> violations = validator.validate(props);
        if (!violations.isEmpty()) {
            throw new ConstraintViolationException(violations);
        }
        return props;
    }
}

然后修改MyProps类,去掉@Validated:

public class MyProps implements Serializable {
    // 你的属性和校验注解(比如@NotNull、@Size等)保留
}

这样MyProps不会被代理,序列化时完全是普通的Serializable对象,不会有任何问题。

方案二:让代理对象支持序列化

如果你一定要保留@Validated在类上,可以通过自定义序列化逻辑,让序列化时使用原始的MyProps对象而非代理。在MyProps类中添加以下方法:

@ConfigurationProperties(prefix = "myprops")
@Validated
public class MyProps implements Serializable {
    // 你的属性和校验注解

    // 序列化时替换为原始目标对象
    private Object writeReplace() throws ObjectStreamException {
        if (this instanceof Advised) {
            try {
                // 获取代理背后的真实MyProps实例
                return ((Advised) this).getTargetSource().getTarget();
            } catch (Exception e) {
                throw new StreamCorruptedException("Failed to unwrap proxy");
            }
        }
        return this;
    }
}

这个方法利用了Java序列化的writeReplace()机制,在序列化前把代理对象替换成真实的MyProps实例,反序列化时就能正常恢复了。

方案三:改用JDK动态代理(仅适用于MyProps是接口的情况)

如果MyProps是一个接口而非类,Spring会使用JDK动态代理(而非CGLIB)。JDK动态代理生成的类默认实现了Serializable,但你需要确保接口本身继承Serializable:

public interface MyProps extends Serializable {
    // 你的属性方法
}

@ConfigurationProperties(prefix = "myprops")
@Validated
public class MyPropsImpl implements MyProps {
    // 实现类逻辑
}

不过这种方式只适用于你能把MyProps改成接口的场景,灵活性不如前两种方案。


内容的提问来源于stack exchange,提问作者Robin-Hoodie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:40:03