我正在尝试组合使用@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
我使用了@EnableAsync
和MethodValidationPostProcessor
的订单属性。
如果我将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。直到现在我还没有解决方案。问题仍然存在...... :(
答案 0 :(得分:0)
两个拦截器都具有相同的order
默认值,因此调用它们的顺序不具有确定性。在您的情况下,首先处理异步注释。
您可以根据您的服务上可能包含的其他拦截器,为您的验证方法提供明确的订单,从而轻松解决此问题,例如
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
processor.setOrder(Ordered.LOWEST_PRECEDENCE - 1);
return processor;
}
您还可以向@EnableAsync
提供订单,明确表示您依赖某个订单。