Spring @Conditional

Class Conditions

Include a configuration bean only if a specified class is present using the @ConditionalOnClass annotation
Include a configuration bean only if a specified class is absent using the @ConditionalOnMissingClass annotation.

@Configuration
@ConditionalOnClass(DataSource.class)
public class MySQLAutoconfiguration {
    //...
}

@Configuration
@ConditionalOnMissingClass(DataSource.class)
public class MySQLAutoconfiguration {
    //...
}

Bean Conditions

Include a bean only if a specified bean is present use the @ConditionalOnBean annotations.
Include a bean only if a specified bean is absent use the @ConditionalOnMissingBean annotations.

@Bean
@ConditionalOnBean(name = "dataSource")
@ConditionalOnMissingBean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource(dataSource());
    em.setPackagesToScan("com.autoconfiguration.example");
    em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    if (additionalProperties() != null) {
        em.setJpaProperties(additionalProperties());
    }
    return em;
}
@Bean
@ConditionalOnMissingBean(type = "JpaTransactionManager")
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);
    return transactionManager;
}

Property Conditions

Use the @ConditionalOnProperty annotation to specify if a configuration loads based on the presence and value of a Spring Environment property.

# 文件 mysql.properties
usemysql=local
@Bean
@ConditionalOnProperty(name = "usemysql", havingValue = "local")
@ConditionalOnMissingBean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true");
    dataSource.setUsername("mysqluser");
    dataSource.setPassword("mysqlpass");
    return dataSource;
}
# configure the dataSource bean using custom properties values

@Bean(name = "dataSource")
@ConditionalOnProperty(name = "usemysql", havingValue = "custom")
@ConditionalOnMissingBean
public DataSource dataSource2() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    dataSource.setUrl(env.getProperty("mysql.url"));
    dataSource.setUsername(env.getProperty("mysql.user") != null ? env.getProperty("mysql.user") : "");
    dataSource.setPassword(env.getProperty("mysql.pass") != null ? env.getProperty("mysql.pass") : "");
    return dataSource;
}

Resource Conditions

The configuration loads only when a specified resource is present use the @ConditionalOnResource annotation.

# 文件 mysql.properties
mysql-hibernate.dialect=org.hibernate.dialect.MySQLDialect
mysql-hibernate.show_sql=true
mysql-hibernate.hbm2ddl.auto=create-drop
@ConditionalOnResource(resources = "classpath:mysql.properties")
public Properties additionalProperties() {
    Properties hibernateProperties = new Properties();
    
    hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("mysql-hibernate.hbm2ddl.auto"));
    hibernateProperties.setProperty("hibernate.dialect", env.getProperty("mysql-hibernate.dialect"));
    hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("mysql-hibernate.show_sql") != null ? env.getProperty("mysql-hibernate.show_sql") : "false");
    return hibernateProperties;
}

Expression Conditional

Use @ConditionalExpression annotation in more complex situations. Spring will use the marked definition when the SpEL expression is evaluated to true:

@Bean
@ConditionalOnExpression("${usemysql} && ${mysqlserver == 'local'}")
DataSource dataSource() {
    // ...
}

Custom Conditions

Use @Conditional to define custom conditions by extending the SpringBootCondition class and overriding the getMatchOutcome() method.

public class HibernateCondition extends SpringBootCondition {

    private static String[] CLASS_NAMES = {"org.hibernate.ejb.HibernateEntityManager", "org.hibernate.jpa.HibernateEntityManager"};

    @Override
    public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {

        ConditionMessage.Builder message = ConditionMessage.forCondition("Hibernate");

        return Arrays.stream(CLASS_NAMES)
                .filter(className -> ClassUtils.isPresent(className, context.getClassLoader()))
                .map(className -> ConditionOutcome.match(message.found("class").items(ConditionMessage.Style.NORMAL, className)))
                .findAny()
                .orElseGet(() -> ConditionOutcome.noMatch(message.didNotFind("class", "classes").items(ConditionMessage.Style.NORMAL, Arrays.asList(CLASS_NAMES))));
    }
}
@Conditional(HibernateCondition.class)
Properties additionalProperties() {
  //...
}

Application Conditions

We can also specify that the configuration can load only inside/outside a web context. In order to do this, we can add the @ConditionalOnWebApplication or @ConditionalOnNotWebApplication annotation.

@ConditionalOnWebApplication
HealthCheckController healthCheckController() {
    // ...
}

Disabling Auto-Configuration Classes

Use the @EnableAutoConfiguration annotation with exclude or excludeName attribute to a configuration class to exclude the auto-configuration from loading.

@Configuration
@EnableAutoConfiguration(exclude={MySQLAutoconfiguration.class})
public class AutoconfigurationApplication {
    //...
}

We can also set the spring.autoconfigure.exclude property

spring.autoconfigure.exclude=com.baeldung.autoconfiguration.MySQLAutoconfiguration

参考: Create a Custom Auto-Configuration with Spring Boot

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值