@Conditional 以 bean 初始化为条件

@Conditional on bean initialization

我已经找了一段时间了。

到目前为止,我发现this博客非常有用,但没有解决我的问题。

只有当 flag 为真时,我才想 @Autowired 一个 bean,否则我希望它是 null

用例:

如果其中一个数据库正在维护,我不希望我的应用程序失败。

@Bean("sqlDatabase")
public Database getSqlDatabase(@Value("${datasource.sql.url}") String url,
        @Value("${datasource.sql.username}") String username, @Value("${datasource.sql.password}") String password,
        @Value("${datasource.poolsize.min}") int minPoolSize, @Value("${datasource.poolsize.max}") int maxPoolSize,
        @Value("${database.enable-sql}") boolean isSqlEnabled) {
    if (isSqlEnabled)
        return Database.builder().url(url).pool(minPoolSize, maxPoolSize).username(username).password(password)
                .build();
    else
        return null;
}

现在,在这种情况下,它抛出错误,因为我不能 autowire 一个 null bean。

我想使用 @Conditional 但我的情况有点复杂。我已经需要更新所有 3 个数据库。如果条件不满足,我只想skip其中之一。

您可以使用配置文件。 每个数据库一个配置文件

  • db1
  • db2
  • db3

比注释 bean class 或带有配置文件的 bean 方法必须激活才能使用该 bean

@Profile("db1")
@Bean("db1")
public Database getSqlDatabase(...){...}       

当您启动您的应用程序时,如果相关配置文件已激活,则只会创建带有 @Profile 注释的 bean。

您可以通过设置 属性 'spring.profiles.active' 来激活配置文件。 激活 db1 和 db2 :

spring.profiles.active=db1,db3

您可以在属性文件中或作为命令行参数设置 属性。

配置文件为您提供了很大的灵活性,可以根据配置spring更改您的上下文

  • 您可以使用相同的配置文件注释许多 bean
  • 您可以使用配置文件
  • 注释配置class
  • 您可以使用配置文件特定的 属性 文件
  • 您可以在一个@Profile 注释中使用多个配置文件。将使用逻辑 'or',因此如果配置文件 'db1' 处于活动状态或配置文件 'db2' 处于活动状态,则将创建一个用 @Profile("db1","db2") 注释的 bean积极的
    • 如果你想要 'or' 以外的东西,你可以使用 @Conditional 来定义你自己的逻辑

请注意:如果您使用不使用组件扫描或 xml 配置,则 bean class 处的注释 @Profile 无效。您需要使用 @Profile 或整个配置 class 来注释 bean 方法。

我们可以在 initial component scan 期间利用 @Conditional 属性 来 避免错误 ,同时基于 环境属性进行初始化.

一个有效的用例是当环境 db.enabled 属性 为 true

时,允许扫描存储库以进行 bean 初始化

示例: https://javapapers.com/spring/spring-conditional-annotation/

条件帮手class

public class DocumentDBInitializerPresence implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        DocumentDBInitializerInfo employeeBeanConfig = null;
        try {
            employeeBeanConfig = (DocumentDBInitializerInfo)context.getBeanFactory().getBean("DocumentDBInitializerInfo");
        } catch(NoSuchBeanDefinitionException ex) {
            System.out.println("BEAN NOT FOUND:: " + employeeBeanConfig != null );
        }
        System.out.println("BEAN FOUND :: " + employeeBeanConfig != null );
        boolean matches = Boolean.valueOf(context.getEnvironment().getProperty("db.enabled"));
        System.out.println("CONFIG ENABLED :: " + employeeBeanConfig != null );
        return employeeBeanConfig != null && matches;
    }
}

正在服务中使用

@Service
@RefreshScope
@Conditional(value= DocumentDBInitializerPresence.class)
public class RepositoryDocumentDB {

    private static Logger LOGGER = LoggerFactory.getLogger(RepositoryDocumentDB.class);

    public static final String DOCUMENT_DB_LOCAL_HOST = "localhost";
    DocumentDBInitializerInfo documentDbConfig;

    @Autowired
    public RepositoryDocumentDB(final DocumentDBInitializerInfo documentDbConfig) {
        this.documentDbConfig = documentDbConfig;
    }
}

如果你没有自动装配,这不会在应用程序启动时抛出错误 RepositoryDocumentDB 任何地方并且 db.enabled 设置为 false。

希望这对您有所帮助!