@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的使用与扩展相关推荐

  1. 一篇文章教你读懂Spring @Conditional注解

    文章目录 一.Conditional简介 二.Conditional用法 1.Conditonal注解作用在方法上 2.Conditonal注解作用在类上 3.类上注入多个条件类 三.Conditio ...

  2. Spring @Conditional相关

    最本质的需求是根据条件加载Bean. Spring4 提供了实现方案 - @Conditional ,可以通过条件判断创建 Bean . 示例: // java config @Configurati ...

  3. Spring 的微内核与FactoryBean扩展机制--转载

    作者:江南白衣 原文地址: http://www.blogjava.net/calvin/archive/2005/08/30/11099.html http://www.blogjava.net/c ...

  4. Spring - @Conditional全解

    文章目录 作用 扩展注解 Code Bean1 Bean2 自定义比较规则 配置类 测试类 如何校验自动配置类是否生效 作用 必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里 ...

  5. Spring @Conditional

    目录 @Conditional的使用 其他派生注解 源码解析 @Conditional 加载流程 ConditionEvaluator Spring boot派生注解 @ConditionalOnBe ...

  6. SpringBoot2 | Spring IOC 流程中核心扩展接口的12个扩展点源码分析(十一)

    微信公众号:吉姆餐厅ak 学习更多源码知识,欢迎关注. SpringBoot2 | SpringBoot启动流程源码分析(一) SpringBoot2 | SpringBoot启动流程源码分析(二) ...

  7. 秒懂SpringBoot之Spring对象生命周期与扩展点浅尝辄止

    [版权申明] 非商业目的注明出处可自由转载 出自:shusheng007 文章目录 概述 Bean的生命周期 感受Bean生命周期 具体说明 扩展点 容器级扩展点 对象级扩展点 多一点 总结 概述 I ...

  8. Spring @Conditional注解 详细讲解及示例

    前言: @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean. @Conditional的定义: //此注解可以标注在类和方法上 @Tar ...

  9. Spring @Conditional注解

    背景 团队所负责的一个项目由于功能的不断累加目前变的十分庞大,打算将其拆分成若干个单独的service,在这之中有一些共用的bean(例如interceptor, datasource等)需要移到一个 ...

最新文章

  1. 下午花一小时整理的JVM运行时方法区
  2. 【es6】es6学习笔记
  3. 数据结构:在下述几种树中,()可以表示静态查找表?
  4. React 点击按钮显示div与隐藏div
  5. python 判断时间是否大于6点_python - 在dataframe中,如何检查时间增量是否大于一分钟?_pandas_酷徒编程知识库...
  6. vue 保存时清空iuput_Vue 一键清空表单的实现方法
  7. 游戏盒子源码_如何用8K电视盒子组建“家庭影院”(设备入门篇)
  8. 利用selenium模块配合chromedriver把html文件转换为图片
  9. 蓝桥杯 ADV-13 算法提高 最小乘积(提高型)
  10. 昨晚调试一段PHP程序时遇到的三个问题
  11. Highlighter与BooleanQuery查询
  12. finedb(内置的HSQL数据库)迁移数据到MySQL
  13. Maxwell个人初学经验及资料分享
  14. 手机号码归属地查询,手机号码归属地批量查询
  15. SqlServer2005使用top 100 PERCENT 无法排序的问题
  16. 31岁才转行程序员,目前34了,我来说说我的经历和一些感受吧...
  17. WPS文档怎样转换为图片
  18. 添加背景音乐(visual stdio2019)
  19. layui 单图片上传 多图片批量上传
  20. 重庆专科计算机大学排名,重庆2017年专科大学排名一览表

热门文章

  1. 求n的阶乘(C语言)
  2. linux系统 ns3安装,ubuntu系统下ns3实验基础指令
  3. Scoop 包管理工具安装及常用命令
  4. java 逆波兰_逆波兰表达式算法-Java版
  5. 原来真有外挂,QQ自动抢红包,JAVA可以实现!卧槽
  6. 用verilog实现L293D 驱动板接口
  7. 数据质量问题根源剖析
  8. jdk支持arm_毕昇JDK,重现了 “活字印刷术” 的传奇
  9. 基于ARKit的iOS无限屏实现,还原锤子发布会效果
  10. vue日期时间转换为年月日格式