SpEL @ConditionalOnProperty字符串属性为空或为空

use*_*237 3 java spring datasource spring-el spring-boot

我目前在我的applications.yaml文件中具有String属性的情况下,无法创建dataSource bean。

理想情况下,仅当在application.yaml文件中设置了URL时,我才想创建dataSource bean。如果bean不存在(空或null),则不应创建。我知道这种情况会检查布尔值,但是否仍然要检查string属性为空还是null?

数据库配置文件

@Configuration
public class DatabaseConfig {
    @Value("${database.url:}")
    private String databaseUrl;

    @Value("${database.username:}")
    private String databaseUsername;

    @Value("${database.password:}")
    private String databasePassword;

    protected static final String DRIVER_CLASS_NAME = "com.sybase.jdbc4.jdbc.SybDriver";


    /**
     * Configures and returns a datasource. Optional
     *
     * @return A datasource.
     */
    @ConditionalOnProperty(value = "database.url")
    @Bean
    public DataSource dataSource() {
        return DataSourceBuilder.create()
            .url(testDatabaseUrl)
            .username(testDatabaseUsername)
            .password(testDatabasePassword)
            .build();
    }
}
Run Code Online (Sandbox Code Playgroud)

application.yml(此字段为可选)

database:
  url: http://localhost:9000
Run Code Online (Sandbox Code Playgroud)

sfu*_*ger 13

你可以使用@ConditionalOnExpression一个春天表达式语言(规划环境地政司)表达式的值:

@ConditionalOnExpression("!T(org.springframework.util.StringUtils).isEmpty('${database.url:}')")
@Bean
public DataSource dataSource() {
    // snip
}
Run Code Online (Sandbox Code Playgroud)

为了更好的可读性和可重用性,您可以将其转换为注释:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ConditionalOnExpression("!T(org.springframework.util.StringUtils).isEmpty('${database.url:}')")
public @interface ConditionalOnDatabaseUrl {
}

@ConditionalOnDatabaseUrl
@Bean
public DataSource dataSource() {
    // snip
}
Run Code Online (Sandbox Code Playgroud)

  • @Hong `T(..)` 是引用类型,与泛型无关。我假设您正在考虑“<T>”。这是 SpEL 参考:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions-types (2认同)

and*_*rii 5

我有同样的问题。正如我不了解的那样,您正在寻找“财产存在而不是空”的状况。这种情况并非开箱即用,因此需要一些编码。解决方案org.springframework.context.annotation.Conditional适用于我:

  1. 创建ConditionalOnPropertyNotEmpty注释和伴随的OnPropertyNotEmptyCondition类,如下所示:

    // ConditionalOnPropertyNotEmpty.java
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.context.annotation.Conditional;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import java.util.Map;
    
    @Target({ ElementType.TYPE, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    @Conditional(ConditionalOnPropertyNotEmpty.OnPropertyNotEmptyCondition.class)
    public @interface ConditionalOnPropertyNotEmpty {
        String value();
    
        class OnPropertyNotEmptyCondition implements Condition {
    
            @Override
            public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
                Map<String, Object> attrs = metadata.getAnnotationAttributes(ConditionalOnPropertyNotEmpty.class.getName());
                String propertyName = (String) attrs.get("value");
                String val = context.getEnvironment().getProperty(propertyName);
                return val != null && !val.trim().isEmpty();
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 用注释您的bean ConditionalOnPropertyNotEmpty,例如:

    @ConditionalOnPropertyNotEmpty("database.url")
    @Bean
    public DataSource dataSource() { ... }
    
    Run Code Online (Sandbox Code Playgroud)

-

另外,您可以将detabase.url显式设置为false(例如detabase.url: false),也可以完全不在detabase.url配置中定义。然后,@ConditionalOnProperty(value = "database.url")将按预期为您工作。


ale*_*x.b 1

您可以尝试更通用的注释,这是 Spring Core 的标准: org.springframework.context.annotation.Conditional

在回调的上下文对象中,您可以获得所需的所有信息:org.springframework.context.annotation.Condition

您也可以考虑使用配置文件。