我正在尝试结合使用@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
我试过 @EnableAsync
和 MethodValidationPostProcessor
的顺序属性。
如果我将 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/