springboot的@ConditionalOnBean注解
上篇文章中分析了springboot的自动注入的原理,可在文章后面的推荐阅读中温习哦。在自动注入的原理那篇文章中提到了@ConditionalOnXX注解,今天来看下springboot中的@ConditionalOnXX注解,该注解表示的是一类注解。马上开始吧。
一、@ConditionalOnXX注解初识
@ConditionalOnXX注解被定义在了spring-boot-autoconfigure包中,有以下几个,

从上图中可以看到经常碰到的@ConditionalOnBean、@ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnMissingClass、@ConditionalOnProperty、@ConditionalOnResource、@ConditionalOnSingleCandidate等。这些注解均在”org.springframework.boot.autoconfigure.condition“包下,感兴趣的小伙伴可以自行查看源码。
二、深入@ConditionalOnBean注解
上面提到了多个@ConditionalOnXX注解,下面逐一对这些常见的注解进行讲解。有意思的是,这些注解很多都是成对出现的,而且意思都是相近的。今天先来看下@CondtionalOnBean注解
2.1、@ConditionalOnBean
@ConditionalOnBean注解的定义如下,

可以明确的一点是@ConditionalOnBean可以用在类/方法上。可以配置的属性有下面这些,

平时用的比较多的有value、type、name三个,这三个可以看到都是数组,也就是说可以配置多个。
上面提到@ConditionalOnBean可以配置在方法上,是所有的方法都可以吗?
2.2、@ConditionalOnBean如何标识方法
@ConditionalOnBean标识在方法上,可以标识在所有的方法上吗,这个我们要从该注解的注释上去找答案了。

从上面的注释可以知道,@ConditionalOnBean注解使用在@Bean标识的方法上,都知道@Bean注解的作用是向容器中注入一个bean,也就是@ConditionalOnBean作用的时机是在生成bean的时候。再看注释“the bean class defaults to return type of the factory method”,大体意思是默认返回的bean是工厂方法的类型,这个不好理解,通过一个例子看下。
2.2.1、@ConditionalOnBean(value=)
MyAutoConfig.java
package com.my.template.config;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 配置类
* @date 2022/7/2 15:02
*/
@Configuration
public class MyAutoConfig {
@Bean(value = "classA")
public ClassA classA(){
return new ClassA();
}
@Bean
@ConditionalOnBean(value = {ClassA.class})
public ClassB classB(){
return new ClassB();
}
}
在上面的配置类中,在@Bean注解的方法上使用了@ConditionalOnBean注解,注解中使用的value属性,代表的是只要存在ClassA这个类边会执行classB()方法,下面看ClassA和ClassB都很简单,就是两个普通的类,
ClassA.java和ClassB.java
package com.my.template.config;
/**
* @date 2022/7/2 15:03
*/
public class ClassA {
public ClassA() {
System.out.println("constructor classA");
}
}
package com.my.template.config;
/**
* @date 2022/7/2 15:04
*/
public class ClassB {
public ClassB() {
System.out.println("constructor classB");
}
}
看下启动日志是否会打印构造方法中的日志,

可以看到正常打印了,也就是说ClassA和ClassB均被注入到了容器中,这是使用@ConditionalOnBean(value=)的情况,下面看使用@ConditionalOnBean(type=)的情况,
2.2.2、@ConditionalOnBean(type=)
这里的type要求填入的是类的全路径,比如com.my.template.config.ClassA
把配置类中修改为下面的样子,

再次启动观察日志,

从日志中可以看到依旧是可以的,下面我把MyAutoConfig类中的classA()方法,放到classB()方法下面,

再执行看日志,

可以看到没有执行ClassB的构造方法,也就是classB()方法没执行。可以得出:在配置类中的@Bean标识的方法是有顺序的,前边的会先解析,后边的后解析,后面的要引用前面的是引用不到的,反之则可以。
这种方式下,没有其他方式可以执行classB()方法吗,有的,使用@ConditionalOnClass(value={ClassA.class}),感兴趣的小伙伴可以自己试试哦。
2.2.3、@ConditionalOnBean(name=)
下面看使用name属性的情况,
MyAutoConfig.java修改成下面的样子,

启动日志如下,

正常启动,且初始化了ClassB类。
2.3、ConditionalOnBean标识类
这里说的标识类,我们一般都默认为标识配置类,即带有@Configuration注解的类。这里同时会有value、type、name三种不同的属性配置,需要注意的是value配置的是Class对象,标识的是只要在解析过程中加载了该类即可。type配置的是全类名,name配置的是bean的名称,type和name的配置要求的是需要解析了该BeanDefinition,同时和顺序是有关系的。演示下面的例子
MyAutoConfig.java
package com.my.template.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 自动配置类
* @date 2022/7/2 15:02
*/
@Configuration
@ConditionalOnBean(type = {"com.my.template.config.ClassA"})
public class MyAutoConfig {
public MyAutoConfig(){
System.out.println("constructor MyAutoConfig");
}
}
MyAutoConfig2.java
package com.my.template.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 自动配置类
*
* @author wangcj5
* @date 2022/7/2 15:02
*/
@Configuration
public class MyAutoConfig2 {
@Bean
public ClassA classA(){
return new ClassA();
}
public MyAutoConfig2(){
System.out.println("constructor MyAutoConfig2");
}
}
启动日志如下,

可以看到实例化了MyAutoConfig2,但是MyAutoConfig确没有,这是因为其类上有@ConditionalOnBean(type = {"com.my.template.config.ClassA"})注解,且在解析MyAutoConfig时并未解析ClassA,把该注解换成@ConditionalOnBean(value= {ClassA.class})看看可以吗

可以看到还是不行,那么换成@ConditionalOnClass(value={ClassA.class})

完美解决问题。
三、总结
本文主要分析了@ConditionalOnBean注解的使用场景,
1、该注解的作用时机是在生成bean的时候,确切的说是在解析beanDefinition的时候
2、该注解可以用在配置类和标识有@Bean的方法上;
3、三个常用属性value、name、type均有解析顺序的问题;
4、value、name、type各自的配置方式
本次分享就到这里了,下次,我们@ConditionalOnClass注解见。
推荐阅读

springboot的@ConditionalOnBean注解的更多相关文章
- springboot的@ConditionalOnClass注解
大家好,我是"良工说技术". 今天给大家带来的是springboot中的@ConditionalOnClass注解的用法.上次的@ConditionalOnBean注解还记得吗? ...
- SpringBoot的条件注解源码解析
SpringBoot的条件注解源码解析 @ConditionalOnBean.@ConditionalOnMissingBean 启动项目 会在ConfigurationClassBeanDefini ...
- springboot整合mybaits注解开发
springboot整合mybaits注解开发时,返回json或者map对象时,如果一个字段的value为空,需要更改springboot的配置文件 mybatis: configuration: c ...
- SpringBoot 中常用注解
本篇博文将介绍几种SpringBoot 中常用注解 其中,各注解的作用为: @PathVaribale 获取url中的数据 @RequestParam 获取请求参数的值 @GetMapping 组合注 ...
- SpringBoot 中常用注解@PathVaribale/@RequestParam/@GetMapping介绍
SpringBoot 中常用注解@PathVaribale/@RequestParam/@GetMapping介绍 本篇博文将介绍几种如何处理url中的参数的注解@PathVaribale/@Requ ...
- springboot整合redis(注解形式)
springboot整合redis(注解形式) 准备工作 springboot通常整合redis,采用的是RedisTemplate的形式,除了这种形式以外,还有另外一种形式去整合,即采用spring ...
- SpringBoot整合Mybatis注解版---update出现org.apache.ibatis.binding.BindingException: Parameter 'XXX' not found. Available parameters are [arg1, arg0, param1, param2]
SpringBoot整合Mybatis注解版---update时出现的问题 问题描述: 1.sql建表语句 DROP TABLE IF EXISTS `department`; CREATE TABL ...
- @Dependson注解与@ConditionalOnBean注解的区别
@Dependson注解是在另外一个实例创建之后才创建当前实例,也就是,最终两个实例都会创建,只是顺序不一样 @ConditionalOnBean注解是只有当另外一个实例存在时,才创建,否则不创建,也 ...
- SpringBoot使用Mybatis注解进行一对多和多对多查询(2)
SpringBoot使用Mybatis注解进行一对多和多对多查询 GitHub的完整示例项目地址kingboy-springboot-data 一.模拟的业务查询 系统中的用户user都有唯一对应的地 ...
随机推荐
- 2021.08.06 P2441 角色属性树(树形结构)
2021.08.06 P2441 角色属性树(树形结构) P2441 角色属性树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 求离x最近的祖先y且(x,y)>1. ...
- 【虚拟机】VMware-open-vm-tools安装
open-vm-tools(VMware-tools的进化版) VMware Tool 和 open-vm-tools任选一样安装即可 在终端进入超级用户 换源下载,依次输入下面命令 sudo cp ...
- ABP框架入门
技术要求 在开始使用 ABP 框架之前,您需要在计算机上安装一些工具. IDE/编辑器 本书假设您使用的是Visual Studio 2022(支持 .NET 6.0 的 v10.0)或更高版本.如果 ...
- Python自定义排序及我实际遇到的一些题目实例
写在前面,本文主要介绍Python基础排序和自定义排序的一些规则,如果都比较熟悉,可以直接翻到第三节,看下实际的笔试面试题中关于自定义排序的应用. 一.基础排序 排序是比较基础的算法,与很多语言一样, ...
- 三个小项目入门Go语言|字节青训营笔记
前言 这是青训营的第一课,今天的课程比较快速的讲解了go语言的入门,并配合三个小的项目实践梳理所学知识点,这里详细回顾一下这三个项目,结合课后作业要求做一些代码补充,并附上自己的分析,青训期间的所有课 ...
- 1903021121—刘明伟—Java第四周作业—java分支语句学习
项目 内容 课程班级博客链接 19信计班(本) 作业要求链接 第四周作业 要求 每道题要有题目,代码(使用插入代码,不会插入代码的自己查资料解决,不要直接截图代码!!),截图(只截运行结果). 扩展阅 ...
- VMware 虚拟机图文安装和配置 AlmaLinux OS 8.6 教程
前言: 这是<VMware 虚拟机图文安装和配置 Rocky Linux 8.5 教程>一文的姐妹篇教程,如果你需要阅读它,请点击这里. 2020 年,CentOS 宣布:计划未来将重心从 ...
- 使用ROOT用户运行Jenkins
!本教程仅适用于以YUM.APT等包管理器安装的Jenkins. 使用ROOT用户运行Jenkins,以保证Jenkins以最高权限执行任务. 注:会存在安全风险! 1.找到Jenkins启动脚本 通 ...
- STM32 CubeMx使用教程
一.STM32CubeMX 简介 STM32CubeMX 是 ST 意法半导体近几年来大力推荐的STM32 芯片图形化配置工具,目的就是为了方便开发者, 允许用户使用图形化向导生成C 初始化代码,可以 ...
- P4169 [Violet]天使玩偶
两种操作:1.加入点(x,y); 2.查询距(x,y)最近的点的曼哈顿距离距离 思路:绝对值拆开通常可以取max,不过这里直接分类讨论4种情况,我们发现如果找\(i\)点左下点\(j\)\((x_j& ...