SpringBoot教程(6) @Conditional 详细讲解和示例
@Conditional 详细讲解和示例
一、@Conditional简介
在开发基于SpringBoot的项目时,经常看到下面的注解:
- ConditionalOnProperty
- ConditionalOnResource
- ConditionalOnBean
- ConditionalOnClass
- ConditionalOnMissingBean
- ConditionalOnMissingClass
虽然能大致上理解它们的用途,并且能简单使用,但是还是想更加深入的学习下这些条件装配注解。
看了B站尚硅谷雷丰阳老师的《Spring注解驱动教程》,简单整理如下笔记。
上面注解在定义时,都有 @ C o n d i t i o n a l \color{red}{@Conditional} @Conditional注解修饰,例如下面:
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
//省略其它
}
@Conditional的定义:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}
- @ C o n d i t i o n a l \color{red}{@Conditional} @Conditional的作用是按照一定的条件进行判断,满足条件给容器注册Bean
- 从代码中可以看到,需要传入一个 C l a s s 数 组 \color{red}{Class数组} Class数组,并且需要继承Condition接口
- Condition是个 接 口 \color{red}{接口} 接口,需要实现matches方法,返回true则注入Bean,false则不注入
二、示例:加载2个Bean
1. 定义Person类
@Data
public class Person {
private String name;
private int age;
public Person(){
System.out.println("初始化:Person()");
}
public Person(String name, int age) {
System.out.println("初始化:Person(String name, int age)");
this.name = name;
this.age = age;
}
}
2. 利用@Configuration + @Bean加载2个Bean
利用@Configuration + @Bean加载2个Bean
@Configuration
public class MyBeanConfig {
@Bean
public Person person1(){
return new Person("Bill Gates", 66);
}
@Bean
public Person person2(){
return new Person("Linus", 50);
}
}
3. 测试是否都加载到Spring容器中
@SpringBootApplication
public class DictApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(DictApplication.class, args);
Map<String, Person> personMap = run.getBeansOfType(Person.class);
System.out.println(personMap);
}
}
结果如下:
{person1=Person(name=Bill Gates, age=66), person2=Person(name=Linus, age=50)}
三、利用@Conditional根据条件加载Bean
1. 创建条件判断的类
如果是Windows系统则加载Bean
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
String property = env.getProperty("os.name");
if (property.contains("Windows")){
return true;
}
return false;
}
}
如果是Linux系统则加载Bean
public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
String property = env.getProperty("os.name");
if (property.contains("Linux")){
return true;
}
return false;
}
}
2. @Conditional放在 方 法 上 \color{red}{方法上} 方法上
@Conditional放在方法上,只能决定该单个方法返回的实例是否加载到容器
@Configuration
public class MyBeanConfig {
@Bean
@Conditional(WindowsCondition.class)
public Person person1(){
return new Person("Bill Gates", 66);
}
@Bean
@Conditional(LinuxCondition.class)
public Person person2(){
return new Person("Linus", 50);
}
}
因为我这是Windows 10,所以返回如下:
{person1=Person(name=Bill Gates, age=66)
3. @Conditional放在 类 上 \color{red}{类上} 类上
@Conditional放在类上,则可以判断该类下一组的Bean是否可以加载到Spring容器
@Configuration
@Conditional(WindowsCondition.class)
public class MyBeanConfig {
@Bean
//@Conditional(WindowsCondition.class)
public Person person1(){
return new Person("Bill Gates", 66);
}
@Bean
//@Conditional(LinuxCondition.class)
public Person person2(){
return new Person("Linus", 50);
}
}
因为我这是Windows 10,@Conditional(WindowsCondition.class)生效可用,所以返回如下:
{person1=Person(name=Bill Gates, age=66), person2=Person(name=Linus, age=50)}
4. @Conditional传 多 个 \color{red}{多个} 多个条件,是 且 \color{red}{且} 且关系
@Conditional接受一个Class数组,可以传多个条件,当所有条件都是true时,才生效
可想项目的代码是不会加载Person对象的,因为
WindowsCondition.class返回 true,
LinuxCondition.class返回 false,
所以MyBeanConfig整个类失效,不能加载它下面的Bean。
@Configuration
@Conditional({WindowsCondition.class, LinuxCondition.class})
public class MyBeanConfig {
@Bean
//@Conditional(WindowsCondition.class)
public Person person1(){
return new Person("Bill Gates", 66);
}
@Bean
//@Conditional(LinuxCondition.class)
public Person person2(){
return new Person("Linus", 50);
}
}
相关文章
- Docker安装Jenkins 从GitLab上拉取代码打包SpringBoot项目并部署到服务器
- 微服务技术系列教程(38)- SpringBoot -整合SpringSecurity
- 微服务技术系列教程(13) - SpringBoot - 其它
- 微服务技术系列教程(10) - SpringBoot - 监控管理 - Admin-UI
- 分布式系列教程(30) -SpringBoot整合ElasticSearch
- 使用docker部署springboot项目小白教程
- springboot + dubbo + zookeeper入门到实战超级详解
- SpringBoot的yaml语法
- SpringBoot与MybatisPlus整合之SQL分析插件(六)
- 《SpringBoot篇》23.SpringBoot整合JavaMail实现发送邮件详解
- 《SpringBoot篇》18.SpringBoot整合Memcached缓存超详细教程
- SpringBoot 自定义Banner
- springboot @EnableAsync 异步,springboot @Async不生效
- SpringBoot 指标监控 Actuator
- 浅析springboot的@Cacheable加入缓存@CacheEvict清除缓存及spEL表达式编写key
- SpringBoot集合SpringSecurity流程及代码详解和导图详解
- 浅析SpringBoot分层的概念及领域模型中的实体类VO、DTO、DO、PO的概念
- springboot配置静态文件及获取静态资源路径【详细教程】
- springboot国际化(i18n)
- Docker+Nginx部署前后端分离项目(SpringBoot+Vue)的详细教程
- SpringBoot获取全局配置文件的属性以及@ConfigurationProperties实现类型安全的配置
- Java SpringBoot IDEA快速创建单元测试
- springboot思维导图