@Conditional

条件装配:满足@Conditional指定的条件时,则进行组件注入

@Conditional注解下面包含许多注解,如下图:

这些注解各有各的功能,这里挑几个来记录一下。

@ConditionalOnBean注解

个人理解:当该注解标注的方法或类有相应的组件时,才注册为组件,否则就不注册为组件

看一下@ConditionalOnBean的源码,可以初步了解它的用法

在方法上使用

测试代码:
配置类
为了测试这里我把配置类中pet01方法的@Bean注解注释掉

@Configuration
public class MyConfig {@ConditionalOnBean(name = "cat")//当容器中有名为tom的组件的时候,下面的方法才注册为组件@Beanpublic User user01(){User user = new User("张三",19);user.setPet(pet01());return user;}//@Bean("cat")public Pet pet01(){return new Pet("cat");}
}

在主程序输出测试结果:

import com.gcl.demo1helloworld.bean.Pet;
import com.gcl.demo1helloworld.bean.User;
import com.gcl.demo1helloworld.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;@SpringBootApplication(scanBasePackages="com.gcl")
public class Demo1HelloworldApplication {public static void main(String[] args) {//返回IOC容器ConfigurableApplicationContext context = SpringApplication.run(Demo1HelloworldApplication.class, args);//判断容器中是否包含user01这个组件boolean user = context.containsBean("user01");System.out.println("组件中包含user01?"+user);}
}

结果:

结果分析:
可以看到,此时容器中并没有user01这个组件了。

在类上使用

测试代码:
配置类:

/*** @author:小关同学爱吃汉堡* @date: 2021/4/5 17:44*/
@Configuration
@ConditionalOnBean(name="tom")
public class MyConfig {@Beanpublic User user01(){User user = new User("张三",19);user.setPet(pet01());return user;}@Bean("cat")public Pet pet01(){return new Pet("cat");}
}

主程序测试:

import com.gcl.demo1helloworld.bean.Pet;
import com.gcl.demo1helloworld.bean.User;
import com.gcl.demo1helloworld.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;@SpringBootApplication(scanBasePackages="com.gcl")
public class Demo1HelloworldApplication {public static void main(String[] args) {//返回IOC容器ConfigurableApplicationContext context = SpringApplication.run(Demo1HelloworldApplication.class, args);//检查容器中是否有下列组件boolean config = context.containsBean("myConfig");System.out.println("组件中包含config?"+config);boolean user = context.containsBean("user01");System.out.println("组件中包含user01?"+user);boolean cat = context.containsBean("cat");System.out.println("组件中包含cat?"+cat);}
}

结果:

我们可以发现,在配置类本身被否决为组件的情况下,配置类下面的所有配置都不生效了

@ConditionalOnMissingBean注解

个人理解:当给定的在bean不存在时,则实例化当前Bean。
再来看一下它的源码,如下图:

@ConditionalOnMissingBean注解作用在@bean定义上,在容器加载它作用的bean时,检查容器中是否存在目标类型(ConditionalOnMissingBean注解里面的值)的bean了,如果存在这跳过原始bean的BeanDefinition加载动作。

在方法上使用

在方法上使用时存在一些坑,让我困惑了好久
当@ConditionalOnMissingBean注解使用name属性时会有一些问题,如下:
配置类

import ch.qos.logback.core.db.DBHelper;
import com.gcl.demo1helloworld.bean.Pet;
import com.gcl.demo1helloworld.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;/*** @author:小关同学爱吃汉堡* @date: 2021/4/5 17:44*/
@Configuration
public class MyConfig {@Bean//我们在这里使用@ConditionalOnMissingBean注解//按理说,当容器中有名为user02的组件的时候,下面的方法就不会注册为组件@ConditionalOnMissingBean(name = "user02")public User user01(){User user = new User("张三",19);user.setPet(pet01());return user;}@Beanpublic User user02(){User user = new User("张三",19);user.setPet(pet01());return user;}@Bean("cat")public Pet pet01(){return new Pet("cat");}
}

在主程序测试:

import com.gcl.demo1helloworld.bean.Pet;
import com.gcl.demo1helloworld.bean.User;
import com.gcl.demo1helloworld.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;@SpringBootApplication(scanBasePackages="com.gcl")
public class Demo1HelloworldApplication {public static void main(String[] args) {//返回IOC容器ConfigurableApplicationContext context = SpringApplication.run(Demo1HelloworldApplication.class, args);boolean config = context.containsBean("myConfig");System.out.println("组件中包含config?"+config);boolean user01 = context.containsBean("user01");System.out.println("组件中包含user01?"+user01);boolean user02 = context.containsBean("user02");System.out.println("组件中包含user02?"+user02);boolean cat = context.containsBean("cat");System.out.println("组件中包含cat?"+cat);}
}

结果:

这结果跟我们想的不太一样啊,user01那里按理说应该是false的,这什么情况???

问过身边的大佬之后,得出一个很草的结论:
这是一个组件创建顺序的问题,因为@ConditionalOnMissingBean(name = “user02”)执行之前,容器里面还没有名叫user02这个组件…所以user01组件总会被创建

正确的使用姿势如下:
配置类:

import ch.qos.logback.core.db.DBHelper;
import com.gcl.demo1helloworld.bean.Pet;
import com.gcl.demo1helloworld.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;/*** @author:小关同学爱吃汉堡* @date: 2021/4/5 17:44*/
@Configuration
public class MyConfig {@Bean//@ConditionalOnMissingBean(name = "user02")//一般来说在这里使用@ConditionalOnMissingBean注解,//当容器中有名为user02的组件的时候,下面的方法不会注册为组件//但是,这里有一个执行顺序的问题,当执行这条语句的时候,//下面的user02组件还未注册,所以下面的方法是一定会被注册为组件的public User user01(){User user = new User("张三",19);user.setPet(pet01());return user;}@Bean@ConditionalOnMissingBean(name = "user01")//当user01这个组件存在时,下面的方法不注册为组件public User user02(){User user = new User("张三",19);user.setPet(pet01());return user;}@Bean("cat")public Pet pet01(){return new Pet("cat");}
}

主程序代码不变
结果:

这时输出的结果跟我们预期的一致了,user02没有被放到容器里面。

当然,如果我们使用value属性判断时,则不会出现上述的问题,如下:

配置类

import ch.qos.logback.core.db.DBHelper;
import com.gcl.demo1helloworld.bean.Pet;
import com.gcl.demo1helloworld.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;/*** @author:小关同学爱吃汉堡* @date: 2021/4/5 17:44*/
@Configuration
public class MyConfig {@Bean@ConditionalOnMissingBean(value = User.class)public User user01(){User user = new User("张三",19);user.setPet(pet01());return user;}@Beanpublic User user02(){User user = new User("张三",19);user.setPet(pet01());return user;}@Bean("cat")public Pet pet01(){return new Pet("cat");}
}

主程序代码不变
结果:

这时候我们发现user01没有被放入到容器中

在类上使用

在类上使用的话,不能使用该类里面注册的组件作为判断条件,不然条件总是为真,如下:
配置类

import ch.qos.logback.core.db.DBHelper;
import com.gcl.demo1helloworld.bean.Pet;
import com.gcl.demo1helloworld.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;/*** @author:小关同学爱吃汉堡* @date: 2021/4/5 17:44*/
@Configuration
@ConditionalOnMissingBean(name = "cat")//条件装配
public class MyConfig {@Beanpublic User user01(){User user = new User("张三",19);user.setPet(pet01());return user;}@Beanpublic User user02(){User user = new User("张三",19);user.setPet(pet01());return user;}@Bean("cat")public Pet pet01(){return new Pet("cat");}
}

主程序代码同上
结果:

SpringBoot复习:3(@Conditional)相关推荐

  1. springboot中的@Conditional注解

    springboot中使用@Configuration注解完成一个配置类的配置,被该注解标注的类会在程序启动时自动的加载到IOC容器,但如果我们想通过一些条件来控制被@Configuraion注解标注 ...

  2. SpringBoot复习:4(@ImportResource)

    @ImportResource注解 作用:这个注解可以用来导入Spring的配置文件(bean.xml文件). 适用场景: 可以试想一下这样一个场景,老板要你将原来的Spring项目改成SpringB ...

  3. SpringBoot @Configuration •@Import •@Conditional•@ImportResoure基本使用

    一.@Configuration 基本使用 Full模式与Lite模式 • 示例 • 最佳实战 • 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断 • 配置 类组件之间有依赖关系, ...

  4. SpringBoot教程(6) @Conditional 详细讲解和示例

    @Conditional 详细讲解和示例 一.@Conditional简介 二.示例:加载2个Bean 1. 定义Person类 2. 利用@Configuration + @Bean加载2个Bean ...

  5. SpringBoot复习:5(配置绑定)

    配置绑定 在SpringBoot中我们如何读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用呢? 我们可以使用以下两种方式来实现. 方法一:@Configurati ...

  6. SpringBoot复习:2(@Configuration注解)

    @Configuration注解 @Configuration注解的作用是代替以前我们使用的xml配置文件,被注解的类就是配置类,其内部包含有一个或多个被@Bean注解的方法,这些方法将会被Annot ...

  7. SpringBoot @Conditional系列注解

    目录 @ConditionalOnClass.@ConditionalOnMissingClass @ConditionalOnBean.@ConditionalOnMissingBean @Cond ...

  8. SpringBoot - @Conditional

    @Conditional @Conditional注解可以参考Spring学习中的@Conditional,参考地址:https://blog.csdn.net/qq_27062249/article ...

  9. 深入理解SpringBoot之装配条件

    我们知道自动装配是SpringBoot微服务化的核心,它会把META-INF/spring.factoires里配置的EnableAutoConfiguration注册到IOC容器里.但是,请大家考虑 ...

最新文章

  1. 近期活动盘点:大数据应用中日交流论坛、几位专家带你认识Flink、青年自强AI计划 CV免费公开课!(11.12-11.23)...
  2. Java中Split函数的用法技巧
  3. 只读字符串的c语言命令,C语言只读空间 - C 语言程序设计
  4. 信息系统项目管理知识--项目风险管理
  5. MathType插入带序号公式的两种方法
  6. Eclipse中的codetemplates.xml
  7. 第94课 函数的参数 《小学生C++编程入门》 例94.1
  8. 豆瓣爬取电影top250
  9. 开关电源设计-基础视频教程(53集全,含配套资料)-道合顺大数据Infinigo
  10. 那智机器人程序打印_应用程序,机器人程序,无人机和3D打印机:要来附近的学校吗?...
  11. JAVA使用465端口与25端口实现发送邮件的业务,以及执行时常见的错误解决方法
  12. AWS、Azure、谷歌云、阿里云最新全方位比较
  13. Win10下修改git全部配置文件方法
  14. 〖Python 数据库开发实战 - Python与MySQL交互篇④〗- 数据库连接池技术
  15. 内测小程序 今日头条的超级APP梦能顺利实现吗?
  16. 你喜欢吃和不喜欢吃的水果
  17. IIS 7.0下载及其安装全过程图解
  18. Android 手游聚合SDK那些事
  19. 使用自定义的评价函数优化高NA分束器
  20. 清明节。。。路人断魂。。。

热门文章

  1. 在Ubuntu 14.04 64bit上安装StarUML 2.5版本
  2. 关于使用python logging模块的几点总结
  3. Maya游戏角色绑定入门学习教程 Game Character Rigging for Beginners in Maya
  4. 数据库2.0 -- 数据类型和数据表的基本操作
  5. 下载安装 binary editor
  6. 5793. 【NOIP2008模拟】小S练跑步
  7. Hadoop 全分布模式 平台搭建
  8. Log控制台打印设置
  9. 转载-SQL Server各种导入导出数据方式的比较
  10. 是时候开始使用JavaScript严格模式了怎样启用javascri