序列化 @Validated class

Serializing a @Validated class

假设我有一个属性 class 正在 Class 中使用,需要由 Spring 缓存序列化,使用 Redis 作为实现。我还通过使用 Spring 的 @Validated (docs) 注释来验证此 class。

@ConfigurationProperties(prefix = "myprops")
@Validated
public class MyProps implements Serializable {

}

@EnableConfigurationProperties(MyProps.class)
@Named
public class ClassThatNeedsToBeSerialized implements Serializable {
   @Inject
   private MyProps myProps;
}

正在尝试缓存此 class 的实例:

@Inject
private ClassThatNeedsToBeSerialized classThatNeedsToBeSerialized;

@Cacheable("my-cache")
public ClassThatNeedsToBeSerialized fetch() {
   return classThatNeedsToBeSerialized;
}

将使用以下堆栈跟踪抛出异常:

org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.io.NotSerializableException: org.springframework.validation.beanvalidation.MethodValidationInterceptor
        at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:68)
        at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:35)
        at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:94)
        ... 31 common frames omitted
    Caused by: java.io.NotSerializableException: org.springframework.validation.beanvalidation.MethodValidationInterceptor
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
        at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1378)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
        at org.springframework.core.serializer.DefaultSerializer.serialize(DefaultSerializer.java:46)
        at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:63)
        ... 33 common frames omitted 

有什么方法可以序列化带有 @Validated 注释的 class 吗?如果没有,是否有类似的替代方案可以工作?

我已经通过注册 configurationPropertiesValidator bean 解决了这个问题 here:

MyClass 创建自定义验证器:

public class ClassThatNeedsToBeSerializedValidator implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {
        return ClassThatNeedsToBeSerialized.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        //Validate
    }
}

将其注册为 bean:

    @Bean
    public Validator configurationPropertiesValidator() {
        return new ClassThatNeedsToBeSerializedValidator();
    }

ClassThatNeedsToBeSerialized 现在可以实现 Serializable 并且可以毫无问题地进行序列化。这样做的缺点是:

  • 据我所知无法注册多个 configurationPropertiesValidators
  • 没有注释