【spring】@Conditional的使用与扩展
@Conditional的使用
@Conditional可以根据条件来判断是否注入某些Bean。
package com.morris.spring.config;import com.morris.spring.condition.LinuxCondition;
import com.morris.spring.condition.WindowsCondition;
import com.morris.spring.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;@Configuration
public class ConditionalConfig {// 如果是windows系统就注入bill@Conditional(WindowsCondition.class)@Bean(name = "user")public User bill() {return new User("bill", 22);}// 如果是linux系统就注入linus@Bean(name = "user")@Conditional(LinuxCondition.class)public User linus() {return new User("linus", 20);}}
WindowsCondition和LinuxCondition都需要实现Condition接口。
WindowsCondition
package com.morris.spring.condition;import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;public class WindowsCondition implements Condition {/*** 根据条件判断是否注入对应的Bean* @param conditionContext 应用上下文* @param annotatedTypeMetadata 加了@Conditional注解的方法的元数据信息* @return*/@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {String osName = conditionContext.getEnvironment().getProperty("os.name");if(osName.contains("Windows")) {return true;}return false;}
}
LinuxCondition
package com.morris.spring.condition;import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;public class LinuxCondition implements Condition {@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {String osName = conditionContext.getEnvironment().getProperty("os.name");if(osName.contains("linux")) {return true;}return false;}
}
如果要测试LinuxCondition并不需要再linux系统下运行,只需要的启动时设置环境参数:-Dos.name=linux
。
Conditional的扩展
ConditionalOnBean
ConditionalOnBeanc.java
package com.morris.spring.condition;import org.springframework.context.annotation.Conditional;import java.lang.annotation.*;@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {Class<?>[] value() default {};
}
OnBeanCondition.java
package com.morris.spring.condition;import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;import java.util.Map;public class OnBeanCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(ConditionalOnBean.class.getName());Class<?>[] clazz = (Class<?>[]) annotationAttributes.get("value");for (Class<?> aClass : clazz) {Map<String, ?> beans = context.getBeanFactory().getBeansOfType(aClass);if(beans.isEmpty()) {return false;}}return true;}
}
ConditionalOnProperty
ConditionalOnProperty.java
package com.morris.spring.condition;import org.springframework.context.annotation.Conditional;import java.lang.annotation.*;@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {String[] value() default {};
}
OnPropertyCondition.java
package com.morris.spring.condition;import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;import java.util.Map;public class OnPropertyCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(ConditionalOnProperty.class.getName());String[] propertyArray = (String[]) annotationAttributes.get("value");for (String property : propertyArray) {if(!context.getEnvironment().containsProperty(property)) {return false;}}return true;}
}
源码分析
如果Condition返回的是false,那么spirng就不会对方法或类进行解析。
org.springframework.context.annotation.ConditionEvaluator#shouldSkip
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {// 判断类或方法上面是否有@Conditional注解if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {return false;}if (phase == null) {if (metadata instanceof AnnotationMetadata &&ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);}return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);}List<Condition> conditions = new ArrayList<>();for (String[] conditionClasses : getConditionClasses(metadata)) {for (String conditionClass : conditionClasses) {Condition condition = getCondition(conditionClass, this.context.getClassLoader());conditions.add(condition);}}AnnotationAwareOrderComparator.sort(conditions);for (Condition condition : conditions) {ConfigurationPhase requiredPhase = null;if (condition instanceof ConfigurationCondition) {requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();}// 调用condition.matches方法if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {return true;}}return false;
}
【spring】@Conditional的使用与扩展相关推荐
- 一篇文章教你读懂Spring @Conditional注解
文章目录 一.Conditional简介 二.Conditional用法 1.Conditonal注解作用在方法上 2.Conditonal注解作用在类上 3.类上注入多个条件类 三.Conditio ...
- Spring @Conditional相关
最本质的需求是根据条件加载Bean. Spring4 提供了实现方案 - @Conditional ,可以通过条件判断创建 Bean . 示例: // java config @Configurati ...
- Spring 的微内核与FactoryBean扩展机制--转载
作者:江南白衣 原文地址: http://www.blogjava.net/calvin/archive/2005/08/30/11099.html http://www.blogjava.net/c ...
- Spring - @Conditional全解
文章目录 作用 扩展注解 Code Bean1 Bean2 自定义比较规则 配置类 测试类 如何校验自动配置类是否生效 作用 必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里 ...
- Spring @Conditional
目录 @Conditional的使用 其他派生注解 源码解析 @Conditional 加载流程 ConditionEvaluator Spring boot派生注解 @ConditionalOnBe ...
- SpringBoot2 | Spring IOC 流程中核心扩展接口的12个扩展点源码分析(十一)
微信公众号:吉姆餐厅ak 学习更多源码知识,欢迎关注. SpringBoot2 | SpringBoot启动流程源码分析(一) SpringBoot2 | SpringBoot启动流程源码分析(二) ...
- 秒懂SpringBoot之Spring对象生命周期与扩展点浅尝辄止
[版权申明] 非商业目的注明出处可自由转载 出自:shusheng007 文章目录 概述 Bean的生命周期 感受Bean生命周期 具体说明 扩展点 容器级扩展点 对象级扩展点 多一点 总结 概述 I ...
- Spring @Conditional注解 详细讲解及示例
前言: @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean. @Conditional的定义: //此注解可以标注在类和方法上 @Tar ...
- Spring @Conditional注解
背景 团队所负责的一个项目由于功能的不断累加目前变的十分庞大,打算将其拆分成若干个单独的service,在这之中有一些共用的bean(例如interceptor, datasource等)需要移到一个 ...
最新文章
- 下午花一小时整理的JVM运行时方法区
- 【es6】es6学习笔记
- 数据结构:在下述几种树中,()可以表示静态查找表?
- React 点击按钮显示div与隐藏div
- python 判断时间是否大于6点_python - 在dataframe中,如何检查时间增量是否大于一分钟?_pandas_酷徒编程知识库...
- vue 保存时清空iuput_Vue 一键清空表单的实现方法
- 游戏盒子源码_如何用8K电视盒子组建“家庭影院”(设备入门篇)
- 利用selenium模块配合chromedriver把html文件转换为图片
- 蓝桥杯 ADV-13 算法提高 最小乘积(提高型)
- 昨晚调试一段PHP程序时遇到的三个问题
- Highlighter与BooleanQuery查询
- finedb(内置的HSQL数据库)迁移数据到MySQL
- Maxwell个人初学经验及资料分享
- 手机号码归属地查询,手机号码归属地批量查询
- SqlServer2005使用top 100 PERCENT 无法排序的问题
- 31岁才转行程序员,目前34了,我来说说我的经历和一些感受吧...
- WPS文档怎样转换为图片
- 添加背景音乐(visual stdio2019)
- layui 单图片上传 多图片批量上传
- 重庆专科计算机大学排名,重庆2017年专科大学排名一览表