@Conditional 是 Spring4 新增的注解,其内部主要就是利用了 Condition 接口来判断是否满足条件,从而决定是否需要加载Bean并注入到Spring容器中。
定义操作系统的具体行为
操作系统接口
public interface OsEnvironment {
/**
* 更改目录
*
* @return .
* */
String directoryListing();
/**
* 清空屏幕
*
* @return .
*/
String clearScreen();
/**
* 文件复制
*
* @return .
*/
String fileCopy();
}
Windows 环境
public class WindowsEnvironment implements OsEnvironment {
@Override
public String directoryListing() {
return "dir";
}
@Override
public String clearScreen() {
return "cls";
}
@Override
public String fileCopy() {
return "copy";
}
}
Linux 环境
public class LinuxEnvironment implements OsEnvironment {
@Override
public String directoryListing() {
return "ls";
}
@Override
public String clearScreen() {
return "clear";
}
@Override
public String fileCopy() {
return "cp";
}
}
定义操作系统环境条件
Windows 环境条件类
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String osName = conditionContext.getEnvironment().getProperty("os.name");
return !StringUtils.isEmpty(osName) && osName.contains("Windows");
}
}
Linux 环境条件类
public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String osName = conditionContext.getEnvironment().getProperty("os.name");
return !StringUtils.isEmpty(osName) && osName.contains("Linux");
}
}
配置类
根据配置来选择具体实例化哪个操作系统环境信息
@Configuration
@Slf4j
public class ConditionConfiguration {
/**
* 如果满足 LinuxCondition(即: matches 返回 true), 则实例化 LinuxEnvironment
* */
@Bean
@Conditional(LinuxCondition.class)
public OsEnvironment linuxListService() {
log.info("当前服务运行在 Linux 环境");
return new LinuxEnvironment();
}
/**
* 如果满足 WindowsCondition(即: matches 返回 true), 则实例化 WindowsEnvironment
* */
@Bean
@Conditional(WindowsCondition.class)
public OsEnvironment windowsListService() {
log.info("当前服务运行在 Windows 环境");
return new WindowsEnvironment();
}
}
验证
@Slf4j
@Component
public class ServiceInitialize implements InitializingBean {
@Autowired
private OsEnvironment osEnvironment;
@Autowired
private ApplicationContext applicationContext;
@Override
public void afterPropertiesSet() throws Exception {
log.info("InitializingBean init...");
log.info("directoryListing={}", osEnvironment.directoryListing());
log.info("clearScreen={}", osEnvironment.clearScreen());
log.info("fileCopy={}", osEnvironment.fileCopy());
System.out.println("\n\n");
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
log.info(beanDefinitionName);
}
System.out.println("\n\n");
log.info("InitializingBean init end...");
}
}
@ConditionalOnExpression 使用
如果 觉得每个条件都要编写实现类 public class XXX implements Condition
有点繁琐, 可以使用 @ConditionalOnExpression
注解
@Configuration
@Slf4j
public class ConditionConfiguration {
/**
* 如果满足 LinuxCondition(即: matches 返回 true), 则实例化 LinuxEnvironment
* */
@Bean
// @Conditional(LinuxCondition.class)
@ConditionalOnExpression("#{systemProperties['os.name'].contains('Linux')}")
public OsEnvironment linuxListService() {
log.info("当前服务运行在 Linux 环境");
return new LinuxEnvironment();
}
/**
* 如果满足 WindowsCondition(即: matches 返回 true), 则实例化 WindowsEnvironment
* */
@Bean
// @Conditional(WindowsCondition.class)
@ConditionalOnExpression("#{systemProperties['os.name'].contains('Windows')}")
public OsEnvironment windowsListService() {
log.info("当前服务运行在 Windows 环境");
return new WindowsEnvironment();
}
}
Spring框架提供了一系列相关的注解
注解 | 说明 |
| 当给定类型的bean存在并且指定为Primary的给定类型存在时,返回true |
| 当给定的类型、类名、注解、昵称在beanFactory中不存在时返回true.各类型间是or的关系 |
| 与上面相反,要求bean存在 |
| 当给定的类名在类路径上不存在时返回true,各类型间是and的关系 |
| 与上面相反,要求类存在 |
| 当所配置的CloudPlatform为激活时返回true |
| spel表达式执行为true |
| 运行时的java版本号是否包含给定的版本号.如果包含,返回匹配,否则,返回不匹配 |
| 要求配置属性匹配条件 |
| 给定的jndi的Location 必须存在一个.否则,返回不匹配 |
| web环境不存在时 |
| web环境存在时 |
| 要求制定的资源存在 |
// 如果配置属性中显示的声明 study.enable=true ,则当前的整体系才生效
@ConditionalOnProperty(prefix ="study", name="enable", havingValue="true")
// 如果没有显示设置study.enable的值时也会正常加载
@ConditionalOnProperty(prefix ="study", name="enable", havingValue="true", matchIfMissing = true)
- havingValue: 比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置
- matchIfMissing: 缺少该property时是否可以加载。如果为true,没有该property也会正常加载;反之报错
// MybatisAutoConfiguration会在DataSourceAutoConfiguration之后加载
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration implements InitializingBean {
}