Spring Conditional原理与实例
文章目录
- 1. 简介
- 2. 自定义Condition
- 3. @Conditional的原理
- 4. 当Condition遇上SpringBoot
1. 简介
Spring4开始添加了一个Condition接口:
@FunctionalInterface
public interface Condition {boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
condition就是条件的意思,就是检查条件是否满足,检查什么信息的什么条件呢?
信息是从ConditionContext条件上下文中获取:
- BeanDefinitionRegistry:BeanDefinition注册中心
- ConfigurableListableBeanFactory:Spring容器
- Environment:环境、包括环境变量、环境属性、系统变量等
- ResourceLoader:资源加载器
- ClassLoader:类加载器
条件是从AnnotatedTypeMetadata注解元数据获取,所以一看这个接口就可以猜到它是专门为注解扫描准备的,所以还配套了一个@Conditional注解。
如果上面的说明有点抽象,那我们下面看一个简单的例子来加强理解。
2. 自定义Condition
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;public class MomCondition implements Condition {@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {String dw = conditionContext.getEnvironment().getProperty("带娃");return "mom".equalsIgnoreCase(dw);}
}
非常简单,继承Condition接口,实现matches方法,根据环境、容器等信息检查是否满足条件,如果满足返回true,不满足就返回false。
上面的例子就是检查环境属性中有没有"带娃"这个属性,如果有并且等于"mom"则说明满足条件。
那这个Condition到底咋用呢?
接下来,就该@Conditional这个注解上场发挥点作用了。
3. @Conditional的原理
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import vip.mycollege.spring.condition.MomCondition;
import vip.mycollege.spring.condition.PapaCondition;@Configuration
public class ConditionConfig {@Conditional(MomCondition.class)@Beanpublic String mom(){return "allen";}@Conditional(PapaCondition.class)@Beanpublic String papa(){return "bob";}
}
@Conditional注解可以放在方法和类上。
- 放在方法上和@Bean一起使用,表示如果@Conditional注解的参数类matches方法为true这创建这个Bean实例,否则不创建。
- 放在类上结合@Configuration、@ComponentScan判断被注解的类是否需要创建
Spring具体逻辑入口:
- ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod:处理@Bean
- ConfigurationClassParser.processConfigurationClass(ConfigurationClass):处理@Configuration
- ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClass, SourceClass):处理@ComponentScan
处理Condition具体逻辑实现的类与方法:
ConditionEvaluator#shouldSkip
上面的Condition可以通过下面的代码做为启动入口测试一下:
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import vip.mycollege.spring.config.ConditionConfig;public class AnnotationStart {public static void main(String[] args) {System.setProperty("带娃","papa");System.setProperty("带娃","mom");AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionConfig.class);System.out.println(context.containsBean("mom"));System.out.println(context.containsBean("papa"));}
}
4. 当Condition遇上SpringBoot
Spring中的Condition看似平平无奇,但是这个平平无奇指的是古天乐的那个平平无奇。
不信,你看当Condition遇上SpringBoot之后发生了怎样的奇迹。
从此,妈妈再也不用担心我写个Hello World都要研究半天配置和依赖了。
SpringBoot的Condition核心是:SpringBootCondition
就是用模板方法模式封装了一下,主要是为了记录日志和做Condition匹配报告输出。
在SpringBoot中自定义Condition,只需要继承SpringBootCondition,然后基本上就是把matches逻辑放在getMatchOutcome方法中就可以了。
SpringBoot中一些Condition:
Conditional注解 | 作用 |
---|---|
@ConditionalOnJndi | 在JNDI存在的条件下查找指定的位置 |
@ConditionalOnBean | 当容器里有指定Bean的条件下 |
@ConditionalOnJava | 基于JVM版本作为判断条件 |
@ConditionalOnClass | 当类路径下有指定的类的条件下 |
@ConditionalOnProperty | 指定的属性是否有指定的值 |
@ConditionalOnResource | 类路径是否有指定的值 |
@ConditionalOnExpression | 基于SpEL表达式为true的时候作为判断条件才去实例化 |
@ConditionalOnMissingBean | 当容器里没有指定Bean的情况下 |
@ConditionalOnMissingClass | 当容器里没有指定类的情况下 |
@ConditionalOnWebApplication | 当前项目时Web项目的条件下 |
@ConditionalOnOnSingleCandidate | 当指定Bean在容器中只有一个,或者有多个但是指定首选的Bean |
@ConditionalOnNotWebApplication | 当前项目不是Web项目的条件下 |
Spring Conditional原理与实例相关推荐
- spring starter原理和实例
spring starter原理和实例 背景 spring starter实现原理 自定义starter 背景 springboot的一个优势就是starter,利用starter,可以避免一些的繁琐 ...
- Spring MVC 原理探秘 - 一个请求的旅行过程
1.简介 在前面的文章中,我较为详细的分析了 Spring IOC 和 AOP 部分的源码,并写成了文章.为了让我的 Spring 源码分析系列文章更为丰富一些,所以从本篇文章开始,我将来向大家介绍一 ...
- (转)spring源码解析,spring工作原理
转自:https://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/ Spring 的骨骼架构 Spring 总共有十几个组件,但是 ...
- 不同类的方法 事务问题_深入理解 Spring 事务原理
Spring事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的.对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行: 获 ...
- spring解耦原理
spring解耦原理 普通java代码实现功能 class Zhang{void doSome(){Xing xi=new Xing();Xi.doSome();XXX x = new XXX();x ...
- Spring Boot - 自动配置实例解读
文章目录 Pre 启用 debug=true输出自动配置 HttpEncodingAutoConfiguration 什么情况下,Spring Boot 会自动装配 HttpEncodingAutoC ...
- Spring MVC 原理探秘 - 容器的创建过程
1.简介 在上一篇文章中,我向大家介绍了 Spring MVC 是如何处理 HTTP 请求的.Spring MVC 可对外提供服务时,说明其已经处于了就绪状态.再次之前,Spring MVC 需要进行 ...
- modelandview使用过程_面试问烂的 Spring AOP 原理、Spring MVC 过程
点击上方 Java后端,选择 设为星标 优质文章,及时送达 作者:莫那一鲁道链接:www.jianshu.com/p/e18fd44964eb Spring AOP ,SpringMVC ,这两个应该 ...
- 浅谈:Spring Boot原理分析,切换内置web服务器,SpringBoot监听项目(使用springboot-admin),将springboot的项目打成war包
浅谈:Spring Boot原理分析(更多细节解释在代码注释中) 通过@EnableAutoConfiguration注解加载Springboot内置的自动初始化类(加载什么类是配置在spring.f ...
最新文章
- linux tar包 追加
- linux下安装mysql初始化报错:bin/mysqld: error while loading shared libraries: libnuma.so.1
- linux wc -l 对io,linux设备驱动归纳总结(五):2.操作硬件——IO内存
- 数据表_事物码(Transaction Code)信息
- AngularJS集合数据遍历显示
- 区块链系列教程之:比特币的世界
- 【渝粤教育】广东开放大学 软件工程 形成性考核 (50)
- Activity隐式启动IntentFilter
- pythonutf-8是不是二进制_python集合、字符编码、bytes与二进制
- alpine linux安装java,alpinelinux安装openjre
- 数据流重导向 -- 第11章 认识与学习 BASH
- houghlinesp找到多条直线_拿什么拯救焦虑的你,一个有勇气的人终将找到他的路...
- php环境用什么服务器好些_PHP环境部署,Linux真的比Windows好吗?
- 行政区划代码2020(SQL)--(上)
- java有序的Map-LinkedHashMap
- 精简指令集(RISC)和复杂指令集(CISC)的区别
- 服务器的回收站在哪个文件夹,Windows系统回收站的文件保存在哪个磁盘上
- idea报错 Result Maps collection does not contain value for com.
- python字符串前面u、r、b含义以及str、bytes互转
- h0154.加勒比海盗船——最优装载问题 (20 分)
热门文章
- scoop mysql_Window包管理工具scoop
- 【Java】深拷贝和浅拷贝,Cloneable接口
- Windows C++ yolov5->ONNX->TensoRT (ResNet、FCN)
- 玲珑oj 1143 - 计算几何你瞎暴力 思维
- 恒生股票数据接口可以实现更加方便地实时获取上海和深圳市场行情数据吗?
- web前端应届生面试注意事项
- 求教贴,一个可能很白痴的问题,有时间又很闲的大神给解决下
- 返老还童 感 2009-05-16 19:05
- linux下u盘目录带锁,完美解决linux下U盘文件只读的问题
- 和刘诗诗无竞争友情最珍贵