我的编程空间,编程开发者的网络收藏夹
学习永远不晚

spring @Conditional的使用与扩展源码分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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
	@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 {
    
    @Override
    public 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 {
    @Override
    public 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 {
	@Override
	public 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 {
	@Override
	public 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使用内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

spring @Conditional的使用与扩展源码分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Spring很常用的@Conditional注解的使用场景和源码解析

今天要分享的是Spring的注解@Conditional,@Conditional是一个条件注解,它的作用是判断Bean是否满足条件,本文详细介绍了@Conditional注解的使用场景和源码,需要的朋友可以参考一下
2023-05-17

Spring中的Lifecycle接口使用与源码分析

这篇文章主要介绍了Spring中的Lifecycle接口使用与源码分析,LifeCycle接口定义了Spring容器的生命周期,任何被Spring管理的对象都可以实现该接口,需要的朋友可以参考下
2023-05-20

Spring事务源码分析专题(一)JdbcTemplate使用及源码分析

Spring中的数据访问,JdbcTemplate使用及源码分析前言本系列文章为事务专栏分析文章,整个事务分析专题将按下面这张图完成对源码分析前,我希望先介绍一下Spring中数据访问的相关内容,然后层层递进到事物的源码分析,主要分为两个部分JdbcTempl
Spring事务源码分析专题(一)JdbcTemplate使用及源码分析
2019-10-22

Golang中Slice的分析与使用源码解析

这篇文章主要介绍了Golang中Slice的分析与使用(含源码),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-03-09

Spring注解之@Import注解的使用和源码分析

今天主要介绍Spring@Import注解,在Spring中@Import使用得比较频繁,它得作用是导入bean,具体的导入方式有多种,特别在SpringBoot项目中,很多地方都使用到了@Import注解,感兴趣的小伙伴可以参考阅读
2023-05-16

GoLang string与strings.Builder使用源码对比分析

本文小编为大家详细介绍“GoLang string与strings.Builder使用源码对比分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“GoLang string与strings.Builder使用源码对比分析”文章能帮助大家解决
2023-07-05

源码分析Android rinflate的使用

这篇文章主要将从源码的角度带大家一起分析Android rinflate的使用,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的可以了解一下
2023-05-16

源码分析Android LayoutInflater的使用

简单来说,LayoutInflater的工作就是将使用xml文件编写的布局转换成Android里的View对象,并且这也是Android中将xml布局转换成View的唯一方式。本文将从源码带大家了解一下LayoutInflater的具体使用
2023-05-16

Python字符串的使用与f-string源码分析

这篇文章主要介绍了Python字符串的使用与f-string源码分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Python字符串的使用与f-string源码分析文章都会有所收获,下面我们一起来看看吧。Pyt
2023-07-05

spring的异步执行使用与源码详解

这篇文章主要介绍了spring的异步执行使用与源码详解,Spring中通过在方法上设置@Async注解,可使得方法被异步调用,需要的朋友可以参考下
2023-05-20

详解Spring @Profile注解的使用和源码解析

这篇文章主要将通过源码带大家深入了解一下Spring中@Profile注解的原理与使用,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
2023-05-15

layui table组件的扩展性分析与实例展示(探讨layui table组件的可扩展性及其应用实例)

layuitable组件以其灵活性和可扩展性著称,提供丰富的API接口,允许开发者根据需要定制和增强。可以通过插件扩展、API扩展和继承扩展进行扩展。插件扩展引入插件实现额外功能,如行拖拽等;API扩展直接调用API函数操作表格;继承扩展继承table组件并重写关键方法,实现更深入的定制。此外,还可用于动态加载、条件过滤、表单提交和集成其他组件。扩展性优势在于灵活易用、模块化设计和可维护性高。
layui table组件的扩展性分析与实例展示(探讨layui table组件的可扩展性及其应用实例)
2024-04-02

spring-mybatis与原生mybatis使用的示例分析

小编给大家分享一下spring-mybatis与原生mybatis使用的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!原生mybatis使用方法:String resource = "mybatis-config.
2023-05-30

nginx slice模块的使用和源码分析小结

Nginxslice模块用于分片并按需流传输大型文件。通过配置sliceon和slice_max_size,可以启用此模块。该模块包含ngx_http_slice_filter_module(分片文件)和ngx_http_slice_stream_module(流式传输分片)。其性能优化包括并发传输、范围请求和分片缓存。slice模块通过分片文件、支持范围请求和并发传输,有效地优化了流化性能,使其成为流媒体应用程序的理想选择。
nginx slice模块的使用和源码分析小结
2024-04-02

JS中的async与await异步编程及await使用陷阱源码分析

这篇“JS中的async与await异步编程及await使用陷阱源码分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“JS中
2023-07-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录