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 {
//...
}
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;
}
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;
}
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;
}
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() {
// ...
}
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() {
//...
}
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() {
// ...
}
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