我想在初始化其他内容之前执行一个函数来检查数据库配置。但是,无论我使用什么方法,它总是在其他一些组件或服务之后被调用,这并不理想。是否可以将其全局优先级设置为上下文初始化后创建的第一个组件?
我已经尝试了以下方法,下面的实现最接近我想要的,但仍然不完全——因为它是在 Flyway 数据库执行器之后执行的:
@Configuration
class DataSourceConfig(
@Value("\${spring.datasource.url}") private val databaseUrl: String
) {
init {
if (databaseUrl.lowercase().contains("jdbc:sqlite:", ignoreCase = true)) {
err.println("!!! ERROR !!!\n" +
"SQLite isn't supported in the v1 development branch yet.\n" +
"Please either switch to MariaDB or wait for the stable v1 release.\n")
exitProcess(1)
}
}
}
以下是我尝试过的其他选项:
@PostConstruct
,与以下选项同时执行:@Configuration
class DataSourceConfig(
private val dataSource: DataSource
) {
@PostConstruct
fun checkDataSource() {
val databaseUrl = JdbcUtils.extractDatabaseMetaData(dataSource) { it.url }
// ...
}
}
@EventListener(ApplicationReadyEvent::class)
。当其他所有内容都初始化时,它会在最近执行,这不是我想要的。@Configuration
class DataSourceConfig(
@Value("\${spring.datasource.url}") private val databaseUrl: String
) {
@EventListener(ApplicationReadyEvent::class)
fun checkDataSource() {
// ...
}
}
使用
@EventListener(ContextRefreshedEvent::class)
。在我的测试中,这个事件根本没有被调用,并且应用程序在没有调用检查的情况下启动,这导致了一个非常令人困惑的错误消息。
使用
CommandLineRunner
bean,当一切都已经初始化时仍在执行。
@Configuration
class DataSourceConfig {
@Bean
fun checkDataSource(dataSource: DataSource) = CommandLineRunner {
val databaseUrl = JdbcUtils.extractDatabaseMetaData(dataSource) { it.url }
// ...
}
}
根据文档
org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent
事件可能符合您的要求。一旦环境可用,它就会被触发,您可以使用 getEnvironment()
事件的方法访问它。
注意,由于此事件是在这么早的阶段触发的,因此您将无法使用
@EventListener
带注释的方法捕获它。您需要实现 ApplicationListener<ApplicationEnvironmentPreparedEvent>
接口并在 main 方法中手动注册它。像这样的东西
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(App.class);
springApplication.addListeners((ApplicationListener<ApplicationEnvironmentPreparedEvent>) event -> {
ConfigurableEnvironment environment = event.getEnvironment();
//check or modify environment here
});
springApplication.run(args);
}