java - Spring:@Validated 和@Async 不能一起工作

标签 java spring validation asynchronous

我正在尝试结合使用@Validated 和@Async。

已编辑:我想在调用我的服务方法时验证输入对象。但是……没有任何反应。我的服务方法从未被调用。如果我从服务方法中删除 @Async 注释,验证工作正常并且方法主体被执行 ValidationContraintException 按预期抛出。

(部分)配置:

@Configuration
@ComponentScan
@EnableAsync
public class MyConfiguration {

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }   
}

我的服务:

@Service
@Validated
public class MyService {

    @Async
    public void doSomethingAsync(@NotNull @Valid final MyBean myBean) {
        // ...
    }

}

使用该服务的组件:

@Component
public class MyComponent {

    @Autowired
    protected MyService myService;

    public void doSomething(final MyBean myBean) {
        this.myService.doSomethingAsync(myBean); // returned without error
    }
}

我的错误在哪里?我该怎么做才能让它发挥作用?

编辑 #1

起初我忘记描述我用无效的 bean 调用我的方法来强制验证错误。

经过一些调试后,我发现 AnnotationAsyncExecutionInterceptor 在 MethodValidationInterceptor 之前执行。这解释了行为。如果我用无效的 bean 调用我的方法,bean 验证将在执行程序线程中执行。 ValidationConstraintException 永远不会到达我在主线程中的错误处理程序,并且方法 myService.doSomethingAsync(myBean) 的调用没有任何错误。

但是我对此感到困惑。 @EnableAsync 的 apidocs 描述了 AsyncAnnotationBeanPostProcessor 在所有其他后处理器之后执行:

指出顺序 {@link org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor} 应该应用。默认是 {@link Ordered#LOWEST_PRECEDENCE} 以便运行 在所有其他后处理器之后,以便它可以添加顾问 现有代理而不是双重代理。

所以我希望 AnnotationAsyncExecutionInterceptor 在我的方法的所有其他拦截器之后执行。

编辑 #2

依赖项 cglib:cglib:3.1 已添加为项目依赖项,@EnableAsync(proxyTargetClass = true) 似乎没有任何效果。

编辑 #3

我试过 @EnableAsyncMethodValidationPostProcessor 的顺序属性。

如果我将 Ordered.HIGHEST_PRECEDENCE 的顺序设置到 MethodValidationPostProcessor,则无法找到我的服务 bean 进行 Autowiring (出于某种原因),Ordered.HIGHEST_PRECEDENCE + 1 有效.

@Configuration
@ComponentScan
@EnableAsync
public class MyConfiguration {

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        final MethodValidationPostProcessor processor = new MethodValidationPostProcessor();

        processor.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
        return processor;
    }   
}

通过调试器,我可以看到后处理器的顺序符合预期。 MethodValidationPostProcessor 现在排在 AsyncAnnotationBeanPostProcessor 之前。但这对我的方法 doSomethingAsync 的方法拦截器的顺序绝对没有影响。

编辑 #4

目前我只是从我的代码中删除了所有@Async 注释。直到现在我还没有解决方案。问题仍然存在... :(

最佳答案

两个拦截器具有相同的 order 默认值,因此调用它们的顺序是不确定的。在您的情况下,首先处理异步注释。

您可以根据服务中可能拥有的其他拦截器,通过为您的验证方法提供明确的顺序来轻松解决此问题,例如

@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
    MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
    processor.setOrder(Ordered.LOWEST_PRECEDENCE - 1);
    return processor;
}   

您还可以向 @EnableAsync 提供一个命令,以明确表示您依赖某个命令。

关于java - Spring:@Validated 和@Async 不能一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23375459/

相关文章:

java - Junit运行子类调用父类(super class)测试用例

java - 我怎样才能增强这个for循环

java - Spring 使用 new 创建的对象开始事务

java - Spring Boot YAML 配置和列表

spring - 无法获取 MongoDbConnectionException : Failed to authenticate to database

java - Saxon XML 验证 : Cannot delete XML File, 验证失败时

c# - 如何在asp.net c#中验证文本框只输入几个选项​​?

Java数组赋值多个值保留初始数组

java - 在mysql中保存特定格式的数据

javascript - AJV 自定义关键字验证