java - Spring 启动 : Conditional on database type

标签 java spring spring-boot

我有一个 Spring Boot 应用程序,想根据底层 SQL 数据源的类型(使用 spring.datasource.* 属性定义)注入(inject)特定的存储库实现。

我尝试在这里使用自定义条件,但不幸的是,在评估它时我无法获取数据源以检查数据库类型。

我目前的情况是这样的:

@Order(Ordered.LOWEST_PRECEDENCE - 10)
class OnDatabaseTypeCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

        DataSource dataSource = context.getBeanFactory().getBean(DataSource.class);
        // further matching code here

}

应该这样使用:

@ConditionalOnDatabaseType(H2)
public class MyCustomImplementation implements MyRepository {
    // Code
}

但是,当评估条件时,出现未定义数据源的异常:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:348)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)

我假设发生这种情况是因为在构造所有 bean 之前已经检查了条件。有什么方法可以告诉 Spring 在评估此条件之前必须创建数据源?或者这只是不可能使用 Spring 条件?

我想解决的用例如下:应用程序可以运行不同类型的数据库,有些(如 H2)不具备某些功能,如窗口功能。所以我想为某些可能速度较慢但功能仍然正确的数据库提供特殊查询。这种方法的想法是,这些 JDBC 存储库应该易于标记,而无需引入特定的 Spring 配置文件,而只需查看底层数据库(使用 org.springframework.jdbc.support.JdbcUtils)即可。

谢谢

最佳答案

一些条件是在实际创建 bean 时评估的。如果要检查 bean 是否存在,则需要非常小心,因为在那个阶段尝试获取 bean 将导致提前初始化。这是第一个问题。

第二个问题是您的配置(应用程序配置)总是在自动配置之前完全运行。如果 Spring Boot 必须决定是否必须创建一个 DataSource,它应该让应用程序配置有机会提供一个。

您可以实现的唯一方法是通过自动配置,确保您的自动配置在应该提供您正在寻找的 bean 的配置之后运行 (@AutoconfigureAfter) .不管怎样,我都不会像那样直接调用上下文。检查 OnBeanCondition 以了解 Spring Boot 本身是如何做这件事的。因此,您不能将此类条件添加到您的应用配置或通过组件扫描扫描到的组件中。

话虽如此,这个用例对我来说看起来很奇怪。也许我们可以退后一步,您可以解释为什么需要这样做。

关于java - Spring 启动 : Conditional on database type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40217790/

相关文章:

spring-boot - Debug模式下的 Spring Boot 日志不使用 log4j starter 打印

java - InetAddress.getByName 在代理后面失败

java - Spring MVC,将@ExceptionHandler 迁移到 HandlerExceptionResolver 以获得 RESTful 服务

Java "ajp-9009-AsyncTimeout"java.lang.OutOfMemoryError : Java heap space Errors 错误

java - 带有 MySql 的 Spring boot 响应式(Reactive) (Webflux)

spring - 无法执行CommandLineRunner-Spring Batch

java - java中如何在迭代集合的同时同时修改集合中的对象

java - Apache Tomcat :Path Error

java - JPA + Hibernate 出现 NoSuchFieldError

java - 从存储库解析插件 'spring:boot' 的版本时出错