Java Spring@EnableAsync打破了bean的初始化顺序?
我想在SpringBoot应用程序中引入Java Spring@EnableAsync打破了bean的初始化顺序?,java,spring,spring-boot,flyway,spring-async,Java,Spring,Spring Boot,Flyway,Spring Async,我想在SpringBoot应用程序中引入@Async方法(用于并行发送邮件)。 但是,当我将@EnableAsync注释放在应用程序的主@Configuration类(用@SpringBootApplication注释)上时,Flyway DB迁移会在执行DataSourceInitializer(为我的测试运行schema.sql和data.sql)之前执行 涉及“应迁移”数据库表的第一个操作失败 删除@EnableAsync会使一切恢复正常。为什么会发生这种情况?我如何解决(或解决问题) 更
@Async
方法(用于并行发送邮件)。
但是,当我将@EnableAsync
注释放在应用程序的主@Configuration
类(用@SpringBootApplication
注释)上时,Flyway DB迁移会在执行DataSourceInitializer
(为我的测试运行schema.sql和data.sql)之前执行
涉及“应迁移”数据库表的第一个操作失败
删除@EnableAsync
会使一切恢复正常。为什么会发生这种情况?我如何解决(或解决问题)
更新更多发现:@enablesync(mode=AdviceMode.ASPECTJ)
保持数据库设置的原始顺序,但是@Async
方法与调用线程在同一线程上运行。我还看到,Bean“objectPostProcessor”是在@enablesync
不存在或使用@enablesync(mode=AdviceMode.ASPECTJ)
时早期创建的(第三个Bean)。当只使用@EnableAsync
时,这个bean的创建要晚得多
更新2虽然我还无法创建一个复制问题的最小项目,但当我在下面注释掉@EnableWebSocketMessageBroker
时,我发现在受影响的应用程序中恢复了正确的数据库设置顺序:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer
{
...
}
如果存在
@EnableWebSocketMessageBroker
,Bean“webSocketConfig”是创建的第一个Bean(根据信息级控制台输出)。结果是,在我的应用程序中同时存在@enablesync
和@EnableWebSocketMessageBroker
导致了所描述的效果
删除其中一个后,恢复了预期的行为,在这种情况下,DataSourceInitializerPostProcessor
在flyway迁移发生之前创建了DataSourceInitializer
,它触发了schema.sql和data.sql的执行
当两个注释都存在时,名为internalAsyncAnnotationProcessor
的BeanPostProcessor
的注册发生在注册DataSourceInitializePostProcessor
之前
问题的原因是注册internalAsyncAnnotationProcessor
导致创建dataSource
bean作为副作用。这种副作用是由spring为执行@Async
方法而寻找要使用的TaskExecutor
bean引起的。spring意外地获取了clientInboundChannelExecutor
bean,该bean由于@EnableWebSocketMessageBroker
而存在。使用这个bean导致了WebSocketMessagingAutoConfiguration
的实例化,它创建了objectMapper
bean(用于json序列化),该bean使用依赖于数据源的DAO存储库的服务。所有这些豆子都被创造出来了
因为当时甚至没有注册DataSourceInitializerPostProcessor
,DataSourceInitializer
是在flyway迁移发生之后创建的
@EnableAsync
的javadoc说明如下:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer
{
...
}
默认情况下,SimpleAsyncTaskExecutor将用于处理异步方法调用。此外,具有void返回类型的带注释方法不能将任何异常传输回调用方。默认情况下,仅记录此类未捕获的异常
我假设将创建一个SimpleAsyncTaskExecutor
来运行@Async
方法,但是spring选择了一个具有匹配类型的现有bean
因此,这个问题的解决方案是实现异步配置器,并提供我自己的执行器。这在@EnableAsync
的javadoc中也有建议:
要自定义所有这些,请实施AsyncConfigurer并提供:
*通过getAsyncExecutor()方法创建您自己的执行器,以及
*通过getAsyncUncaughtExceptionHandler()方法创建您自己的AsyncUncaughtExceptionHandler
通过此调整,DB设置再次按预期执行。Flyway是否有任何错误?如何确保async stuff仅在迁移完成后运行?请查看我的更新。实际上,迁移似乎很好,整个数据库稍后会重新创建。我不理解这个问题。在尝试使用数据库之前,需要运行迁移代码。为什么要“异步”运行它?不,我不想异步运行任何数据库内容。我想做的异步工作是发送电子邮件。但是,当我在主配置上引入@EnableAsync
时,迁移是在数据库设置之前尝试的。让我知道问题的哪一部分让人困惑,我会尽力纠正。症状不一样,但我想知道是否是由