20-07-02
banq
当使用Spring Boot或仅使用普通的Spring Framework时,可能要延迟应用程序的启动,直到可以与数据库建立正确的连接为止。当使用容器技术(例如Docker)时,情况可能更是如此。
DatabaseStartupValidator会延迟应用程序的进一步启动,直到可以建立与数据库的连接为止。默认情况下,它将每秒尝试连接到数据库,并仅捕获异常。它将尝试60秒,此后如果无法建立连接,则失败(所有这些属性都是可配置的)。
要使用它,只需声明一个bean并注入数据源。您定义一个验证查询(从Spring 5.3开始,它将isValid默认使用JDBC 4 方法!)。Spring Boot附带了一个方便的枚举,该枚举已经包含针对一系列受支持数据库的默认验证查询(由Spring Boot Actuator中的运行状况检查使用)。
@SpringBootApplication public class DatabaseUpApplication { public static void main(String[] args) { SpringApplication.run(DatabaseUpApplication.class, args); } @Bean public DatabaseStartupValidator databaseStartupValidator(DataSource dataSource) { var dsv = new DatabaseStartupValidator(); dsv.setDataSource(dataSource); dsv.setValidationQuery(DatabaseDriver.POSTGRESQL.getValidationQuery()); return dsv; } } |
但是,仅定义此bean可能还不够,需要更多配置。有许多依赖DataSource 的beans如EntityManagerFactory,Flyway 或 JdbcTemplate ,需要手工增加@DependsOn在这些@Bean方法上:可通过Spring Boot进行一些自动配置,也可以使用a BeanFactoryPostProcessor来修改bean
@Bean public static BeanFactoryPostProcessor dependsOnPostProcessor() { return bf -> { // Let beans that need the database depend on the DatabaseStartupValidator // like the JPA EntityManagerFactory or Flyway String[] flyway = bf.getBeanNamesForType(Flyway.class); Stream.of(flyway) .map(bf::getBeanDefinition) .forEach(it -> it.setDependsOn("databaseStartupValidator")); String[] jpa = bf.getBeanNamesForType(EntityManagerFactory.class); Stream.of(jpa) .map(bf::getBeanDefinition) .forEach(it -> it.setDependsOn("databaseStartupValidator")); }; } |
这里延缓了Flyway 和 EntityManagerFactory执行,直到DatabaseStartupValidator 完全初始化。
源代码可以在GitHub上找到。