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

你可能感兴趣的:(Baeldung,学习笔记,框架,spring,android,java)