Spring Boot:以数据库类型为条件

Ger*_*uer 5 java spring spring-boot

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

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

我目前的情况是这样的:

@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

}
Run Code Online (Sandbox Code Playgroud)

它应该像这样使用:

@ConditionalOnDatabaseType(H2)
public class MyCustomImplementation implements MyRepository {
    // Code
}
Run Code Online (Sandbox Code Playgroud)

但是,当评估条件时,我得到一个未定义数据源的异常:

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)
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢

Ste*_*oll 2

实际创建 Bean 时会评估某些条件。如果您想检查 bean 是否存在,则需要非常小心,因为在该阶段获取 bean 的任何尝试都将导致早期初始化。这是第一个问题。

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

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

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

  • 该应用程序是 spring data 和 spring jdbc 的混合体(其中 JPA 不够),问题出在应用程序的 jdbc 部分。我会尝试以不同的方式解决问题,如果遇到问题,我会提出一个新问题。 (2认同)