SpringBoot复习:3(@Conditional)
@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)相关推荐
- springboot中的@Conditional注解
springboot中使用@Configuration注解完成一个配置类的配置,被该注解标注的类会在程序启动时自动的加载到IOC容器,但如果我们想通过一些条件来控制被@Configuraion注解标注 ...
- SpringBoot复习:4(@ImportResource)
@ImportResource注解 作用:这个注解可以用来导入Spring的配置文件(bean.xml文件). 适用场景: 可以试想一下这样一个场景,老板要你将原来的Spring项目改成SpringB ...
- SpringBoot @Configuration •@Import •@Conditional•@ImportResoure基本使用
一.@Configuration 基本使用 Full模式与Lite模式 • 示例 • 最佳实战 • 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断 • 配置 类组件之间有依赖关系, ...
- SpringBoot教程(6) @Conditional 详细讲解和示例
@Conditional 详细讲解和示例 一.@Conditional简介 二.示例:加载2个Bean 1. 定义Person类 2. 利用@Configuration + @Bean加载2个Bean ...
- SpringBoot复习:5(配置绑定)
配置绑定 在SpringBoot中我们如何读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用呢? 我们可以使用以下两种方式来实现. 方法一:@Configurati ...
- SpringBoot复习:2(@Configuration注解)
@Configuration注解 @Configuration注解的作用是代替以前我们使用的xml配置文件,被注解的类就是配置类,其内部包含有一个或多个被@Bean注解的方法,这些方法将会被Annot ...
- SpringBoot @Conditional系列注解
目录 @ConditionalOnClass.@ConditionalOnMissingClass @ConditionalOnBean.@ConditionalOnMissingBean @Cond ...
- SpringBoot - @Conditional
@Conditional @Conditional注解可以参考Spring学习中的@Conditional,参考地址:https://blog.csdn.net/qq_27062249/article ...
- 深入理解SpringBoot之装配条件
我们知道自动装配是SpringBoot微服务化的核心,它会把META-INF/spring.factoires里配置的EnableAutoConfiguration注册到IOC容器里.但是,请大家考虑 ...
最新文章
- 近期活动盘点:大数据应用中日交流论坛、几位专家带你认识Flink、青年自强AI计划 CV免费公开课!(11.12-11.23)...
- Java中Split函数的用法技巧
- 只读字符串的c语言命令,C语言只读空间 - C 语言程序设计
- 信息系统项目管理知识--项目风险管理
- MathType插入带序号公式的两种方法
- Eclipse中的codetemplates.xml
- 第94课 函数的参数 《小学生C++编程入门》 例94.1
- 豆瓣爬取电影top250
- 开关电源设计-基础视频教程(53集全,含配套资料)-道合顺大数据Infinigo
- 那智机器人程序打印_应用程序,机器人程序,无人机和3D打印机:要来附近的学校吗?...
- JAVA使用465端口与25端口实现发送邮件的业务,以及执行时常见的错误解决方法
- AWS、Azure、谷歌云、阿里云最新全方位比较
- Win10下修改git全部配置文件方法
- 〖Python 数据库开发实战 - Python与MySQL交互篇④〗- 数据库连接池技术
- 内测小程序 今日头条的超级APP梦能顺利实现吗?
- 你喜欢吃和不喜欢吃的水果
- IIS 7.0下载及其安装全过程图解
- Android 手游聚合SDK那些事
- 使用自定义的评价函数优化高NA分束器
- 清明节。。。路人断魂。。。
热门文章
- 在Ubuntu 14.04 64bit上安装StarUML 2.5版本
- 关于使用python logging模块的几点总结
- Maya游戏角色绑定入门学习教程 Game Character Rigging for Beginners in Maya
- 数据库2.0 -- 数据类型和数据表的基本操作
- 下载安装 binary editor
- 5793. 【NOIP2008模拟】小S练跑步
- Hadoop 全分布模式 平台搭建
- Log控制台打印设置
- 转载-SQL Server各种导入导出数据方式的比较
- 是时候开始使用JavaScript严格模式了怎样启用javascri