关于bean初始化的@Conditional

时间:2017-02-18 07:41:59

标签: java spring spring-boot conditional autowired

我一直在寻找这个。

直到现在,我发现this博客非常有用,但没有解决我的问题。

我想@Autowired只有当flag为真时才会使用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其中一个。

2 个答案:

答案 0 :(得分:1)

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

  • DB1
  • DB2
  • DB3

使用必须激活的配置文件注释bean类或bean方法以使用该bean,如

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

启动应用时,只有在激活相关配置文件时,才会创建使用@Profile注释的bean。

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

spring.profiles.active=db1,db3

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

配置文件为您提供了很大的灵活性,可以通过配置来更改弹簧上下文

  • 您可以使用相同的配置文件注释许多bean
  • 您可以使用个人资料
  • 注释配置类
  • 您可以使用个人资料特定属性文件
  • 您可以在一个@Profile注释中使用许多配置文件。将使用逻辑'或',因此如果配置文件'db1'处于活动状态或配置文件'db2'处于活动状态,则将创建使用@Profile(“db1”,“db2”)注释的bean
    • 如果您想要除“或”以外的其他内容,您可以使用@Conditional来定义自己的逻辑

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

答案 1 :(得分:1)

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

有效的用例是,当环境db.enabled属性为true时,可以扫描存储库中的bean初始化

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

条件助手类

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。

希望这会有所帮助!