如何让Spring @ConditionalOnProperty检查是否存在一个没有值的属性

6za6bjd0  于 2023-08-02  发布在  Spring
关注(0)|答案(1)|浏览(211)

好吧,我自己的项目有一个专门的配置文件,它可以设置Redis的多源

my:
  redis:
    connections:
      - name: redis-1
        address: 127.0.0.1:6379
        mode: master
      - name: redis-2
        address: 127.0.0.1:6479
        mode: slave
        ofSlave: redis-1
      - name: redis-3
        address: 127.0.0.1:6579
        mode: slave
        ofSlave: redis-1

字符串
我尝试构建一个自动配置类,它将在检测到属性时加载

// @Configuration // controll by @EnableMyRedis
@ConditionalOnProperty("my.redis.connections")
public class MyRedisAutoConfiguration {

}


因此,我希望在application.yml文件包含属性my.redis.connections时加载此配置和其他组件,即使is没有值。
补充说明:
我真正想要的东西可以用这个例子来表示,一个AutoConfiguration和一个PropertyBeanDefinitionRegistrar

@Import(AutoConfiguration.class)
public @annotation EnableMyRedis {
}

@MyConditionalOnProperty(prefix = "my.redis.connections")
@Import(PropertyBeanDefinitionRegistrar.class)
public class AutoConfiguration {

}

public class PropertyBeanDefinitionRegistrar implements
    EnvironmentAware, BeanDefinitionRegistrar {

}


可以很清楚地看到他们的关系;
1.如果已启用,则加载AutoConfiguration,否则不加载
1.如果Have property-prefix 'my.redis. connections',则加载PropertyBeanDefinitionRegistrar,否则不加载
1.在这一步中,property-file将被真正处理并生成bean。
但是我启用了debug: true,发现它不起作用,OnPropertyCondition类的getMatchOutcome方法中的PropertyResolver或Environment只检查了真实的属性,而没有检查图层关系
我如何才能实现我的需求?

gcuhipw9

gcuhipw91#

@ConditionalOnProperty仅在环境属性存在且具有特定值时启用bean注册。
这意味着您不能使用它来检查application.ymlapplication.properties文件中是否存在属性。
我觉得你有两个选择

选项一:在应用属性中添加新属性

可以在应用程序属性文件中添加新属性。
举例来说:

my:
  redis:
    enabled: true
    connections:
      - name: redis-1
        address: 127.0.0.1:6379
        mode: master
      - name: redis-2
        address: 127.0.0.1:6479
        mode: slave
        ofSlave: redis-1
      - name: redis-3
        address: 127.0.0.1:6579
        mode: slave
        ofSlave: redis-1

字符串
用于Map连接属性的对象不需要Map新属性my.redis.enabled,因此它不会影响您读取配置的方式。
现在您可以使用my.redis.enabled

@ConditionalOnProperty("my.redis.enabled")
public class MyRedisAutoConfiguration {}


这是最简单和更好的解决方案IMO

选项二:实现自定义条件

您可以在类中Map配置,例如:

@ConfigurationProperties(prefix = "my.redis")
public class RedisConnectionProperties {
    
    private Map<String, String> connections;

    public Map<String, String> getConnections() {
        return connections;
    }

    public void setConnections(Map<String, String> connections) {
        this.connections = connections;
    }

}


然后实现一个自定义条件,检查Map到RedisConnectionProperties的Redis连接的Map是否为空:

public class RedisConnection implements Condition {

  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    RedisConnectionProperties config = Binder.get(context.getEnvironment())
        .bind("my.redis",RedisConnectionProperties.class)
        .orElse(null);
    return config != null && config.getConnections() != null && !config.getConnections().isEmpty();
  }
}


最后,你可以在MyRedisAutoConfiguration上使用这个条件:

@Conditional(RedisConnection.class)
public class MyRedisAutoConfiguration {}

相关问题