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

时间:2014-04-29 21:17:36

标签: java spring validation asynchronous

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

编辑:我想在调用我的服务方法时验证输入对象。但是......没有任何反应。我的服务方法永远不会被调用。如果我从服务方法中删除@Async annoation,验证工作正常并且方法体被执行,将按预期抛出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进行自动装配(由于某种原因),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的方法incerceptors的顺序完全没有影响。

编辑#4

目前我刚从代码中删除了任何@Async annoations。直到现在我还没有解决方案。问题仍然存在...... :(

1 个答案:

答案 0 :(得分:0)

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

您可以根据您的服务上可能包含的其他拦截器,为您的验证方法提供明确的订单,从而轻松解决此问题,例如

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

您还可以向@EnableAsync提供订单,明确表示您依赖某个订单。