ing容器中是否已经注册了某种类型的Bean(如未注册,我们可以让其自动注册到容器中,上一条同理)。
一个文件是否在特定的位置上。
一个特定的系统属性是否存在。
在Spring的配置文件中是否设置了某个特定的值。
举个栗子,假设我们有两个基于不同数据库实现的DAO,它们全都实现了UserDao,其中JdbcUserDAO与MySql进行连接,MongoUserDAO与MongoDB进行连接。现在,我们有了一个需求,需要根据命令行传入的系统参数来注册对应的UserDao,就像java -jar app.jar -DdbType=MySQL
会注册JdbcUserDao,而java -jar app.jar -DdbType=MongoDB
则会注册MongoUserDao。使用@Conditional可以很轻松地实现这个功能,仅仅需要在你自定义的条件类中去实现Condition接口,让我们来看下面的代码。(以下案例来自:https://dzone.com/articles/how-springboot-autoconfiguration-magic-works)
public interface UserDAO {
....
}
public class JdbcUserDAO implements UserDAO {
....
}
public class MongoUserDAO implements UserDAO {
....
}
public class MySQLDatabaseTypeCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
String enabledDBType = System.getProperty("dbType"); // 获得系统参数 dbType
// 如果该值等于MySql,则条件成立
return (enabledDBType != null && enabledDBType.equalsIgnoreCase("MySql"));
}
}
// 与上述逻辑一致
public class MongoDBDatabaseTypeCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
String enabledDBType = System.getProperty("dbType");
return (enabledDBType != null && enabledDBType.equalsIgnoreCase("MongoDB"));
}
}
// 根据条件来注册不同的Bean
@Configuration
public class AppConfig {
@Bean
@Conditional(MySQLDatabaseTypeCondition.class)
public UserDAO jdbcUserDAO() {
return new JdbcUserDAO();
}
@Bean
@Conditional(MongoDBDatabaseTypeCondition.class)
public UserDAO mongoUserDAO() {
return new MongoUserDAO();
}
}
现在,我们又有了一个新需求,我们想要根据当前工程的类路径中是否存在MongoDB的驱动类来确认是否注册MongoUserDAO。为了实现这个需求,可以创建检查MongoDB驱动是否存在的两个条件类。
public class MongoDriverPresentsCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
try {
Class.forName("com.mongodb.Server");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
public class MongoDriverNotPresentsCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
try {
Class.forName("com.mongodb.Server");
return false;
} catch (ClassNotFoundException e) {
return true;
}
}
}
假如,你想要在UserDAO没有被注册的情况下去注册一个UserDAOBean,那么我们可以定义一个条件类来检查某个类是否在容器中已被注册。
public class UserDAOBeanNotPresentsCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
UserDAO userDAO = conditionContext.getBeanFactory().getBean(UserDAO.class);
return (userDAO == null);
}
}
如果你想根据配置文件中的某项属性来决定是否注册MongoDAO,例如app.dbType
是否等于MongoDB
,我们可以实现以下的条件类。
public class MongoDbTypePropertyCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
String dbType = conditionContext.getEnvironment().getProperty("app.dbType");
return "MONGO&