【问题标题】:Spring @Conditional based on a value in database tableSpring @Conditional 基于数据库表中的值
【发布时间】:2023-03-03 07:59:24
【问题描述】:

条件评估取决于数据库表中提供的值

@Component
public class XYZCondition implements Condition{

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
              //based on value defined in DB should return true/false
    }

}

由于 Condition 执行得非常早,无法获取 db 值 有没有其他方法可以实现这一目标?

【问题讨论】:

  • @levant pied : 我看过类似的问题,你有什么发现
  • 看来您使用 Condition 的目的与它们的用途不同。能否请您详细描述一下您的情况,以便我向您推荐有用的东西?
  • Interface 有多个实现,并且 table 对每个实现的类都有 enable 或 disable 值来决定初始化 bean,所以考虑使用 @Condition 来实现这个?
  • @user1702759 那么你将如何注入那些启用的接口的“多个实现”?

标签: java spring-boot spring-4


【解决方案1】:

可以在应用程序工作期间更改数据库值,但重新加载应用程序上下文似乎不是一个好主意。 所以我建议使用配置属性来选择哪些 bean 应该在上下文中可用。

此外,还有一个 Spring Cloud Config 允许您将配置存储在 git 或其他一些存储中。一旦配置更改,它的消费者可能会重新启动上下文。 看起来也值得一说。

【讨论】:

    【解决方案2】:

    嗯,也许您可​​以创建一个配置类并注入您的存储库,然后创建一个 Bean。然后在 bean 方法内部从数据库中获取值并返回条件实例。像这样的

    @Configuration
    public class Config {
    
    @Autowired  
    private Repository repository;
    
    @Bean
    public Interface interface(){
      boolean val = reposiory.getDBValue();
      if(val)
        return new Impl1();
      else
        return new Impl2();
      }
    }
    

    【讨论】:

      【解决方案3】:

      嗯,你正在尝试做一些不能很好地映射到这种形式的 Spring Boot 的事情。

      我建议稍微改变一下要求:

      与其尝试在自定义条件中访问数据库,不如创建自定义配置源并将属性从数据库加载到环境中,以便稍后在启动过程中评估条件时,具有关联的属性值(之前从数据库中解析)已经可用。

      遵循这种方法的示例如下: - 从“远程”配置服务(通过 REST)读取配置属性的 Spring Boot 云配置 - Spring boot consul 集成(显然是从 consul 读取的)

      这种方法对 spring 更加友好,并且还可以使应用程序免于多次调用数据库(如果您有 100 个具有此自定义条件的 bean 会怎样)- 它会执行 100 次查询吗?

      现在,这意味着您可能不需要自定义条件 - 可能它会是 @Condition 属性。

      另一个需要注意的是,您将无法使用 JPA/Spring Data 加载此属性,可能您必须在此处使用普通 JDBC。

      【讨论】:

        【解决方案4】:

        遗憾的是,您无法在条件中注入很多内容:因此请尝试使用纯 url 并手动连接到服务器, 但在我的情况下,这不起作用,因为我有将相同的配置值添加到数据库中的 flyway 迁移(鸡和蛋问题)

        class EnableXXXCondition implements Condition {
            private Environment environment;
        
            @SneakyThrows
            @Override
            public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
                environment = context.getBeanFactory().getBean(Environment.class);
        
                final String url = environment.getProperty("spring.datasource.url");
                final String user = environment.getProperty("spring.datasource.username");
                final String password = environment.getProperty("spring.datasource.password");
        
                String x;
        
                //we have problems with flyway before
                try (Connection connection = DriverManager.getConnection(url, user, password)) {
                    try (Statement statement = connection.createStatement()) {
                        try (final ResultSet resultSet = statement.executeQuery("select x from y")) {
                            resultSet.next();
                            x = resultSet.getString("x");
                        }
                    }
                }
        
                return Boolean.valueOf(x);
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-01-29
          • 2014-12-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多