@Conditional是Spring4新提供的注解,它的作用是根据某个条件创建特定的Bean,通过实现Condition接口,并重写matches接口来构造判断条件。总的来说,就是根据特定条件来控制Bean的创建行为,这样我们可以利用这个特性进行一些自动的配置。

  本文将分为三大部分,@Conditional源码的介绍、Condition的使用示例和@Conditional的扩展注解的介绍。

一、@Conditional的源码

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional { /**
* All {@link Condition Conditions} that must {@linkplain Condition#matches match}
* in order for the component to be registered.
*/
Class<? extends Condition>[] value(); }
从源码中可以看到,@Conditional注解可以用在类和方法上,需要传入一个实现了Condition接口class数组。

二、代码示例

下面将以不同的操作系统为条件,通过实现Condition接口,并重写其matches方法来构造判断条件。若在Windows系统下运行程序,则输出列表命令为dir;若在Linux系统下运行程序,则输出列表命令为ls。

1.判断条件类的定义

(1).判断Windows的条件
package com.study.day01;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata; /**
* @Auther: lifq
* @Description:
*/
public class WindowsCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("os.name").contains("Windows");
}
}

(2).判断Linux的条件

package com.study.day01;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata; /**
* @Auther: lifq
* @Description:
*/
public class LinuxCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("os.name").contains("Linux");
}
}

2.不同系统下的Bean的类

(1).接口代码
package com.study.day01;

import org.springframework.stereotype.Service;

/**
* @Auther: lifq
* @Description:
*/
public interface ListService { public String showListCmd(); }

 (2).Windows实现类代码

package com.study.day01;

/**
* @Auther: lifq
* @Description:
*/
public class WindowsService implements ListService {
public String showListCmd() {
return "dir";
}
}

(3).Linux实现类代码

package com.study.day01;

/**
* @Auther: lifq
* @Description:
*/
public class LinuxService implements ListService {
public String showListCmd() {
return "ls";
}
}

 3.配置类

package com.study.day01;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; /**
* @Auther: lifq
* @Description:
*/
@Configuration
public class Config { @Bean
@Conditional(WindowsCondition.class)
public ListService window() {
return new WindowsService();
} @Bean
@Conditional(LinuxCondition.class)
public ListService linux() {
return new LinuxService();
}
}

 4.运行类

package com.study.day01;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
* @Auther: lifq
* @Description:
*/
public class Main01 { public static void main (String []args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class); ListService listService = applicationContext.getBean(ListService.class); System.out.println(applicationContext.getEnvironment().getProperty("os.name") + "系统下的列表命令为:" + listService.showListCmd());
}
}

我的是Windows操作系统,输出结果为dir,运行截图如下:

运行截图

@Conditional注解例子演示完成,有问题欢迎留言沟通哦!

完整源码地址:https://github.com/suisui2019/springboot-study

三、@Conditional的扩展注解

@ConditionalOnBean:仅仅在当前上下文中存在某个对象时,才会实例化一个Bean。
@ConditionalOnClass:某个class位于类路径上,才会实例化一个Bean。
@ConditionalOnExpression:当表达式为true的时候,才会实例化一个Bean。
@ConditionalOnMissingBean:仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean。
@ConditionalOnMissingClass:某个class类路径上不存在的时候,才会实例化一个Bean。
@ConditionalOnNotWebApplication:不是web应用,才会实例化一个Bean。
@ConditionalOnBean:当容器中有指定Bean的条件下进行实例化。
@ConditionalOnMissingBean:当容器里没有指定Bean的条件下进行实例化。
@ConditionalOnClass:当classpath类路径下有指定类的条件下进行实例化。
@ConditionalOnMissingClass:当类路径下没有指定类的条件下进行实例化。
@ConditionalOnWebApplication:当项目是一个Web项目时进行实例化。
@ConditionalOnNotWebApplication:当项目不是一个Web项目时进行实例化。
@ConditionalOnProperty:当指定的属性有指定的值时进行实例化。
@ConditionalOnExpression:基于SpEL表达式的条件判断。
@ConditionalOnJava:当JVM版本为指定的版本范围时触发实例化。
@ConditionalOnResource:当类路径下有指定的资源时触发实例化。
@ConditionalOnJndi:在JNDI存在的条件下触发实例化。
@ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者有多个但是指定了首选的Bean时触发实例化。

推荐阅读

1.Spring Boot入门-快速搭建web项目
2.Spring Boot 2.X 整合Redis
3.Spring Boot 2.X 如何优雅的解决跨域问题?
4.Spring Boot 2.X 如何添加拦截器?
5.Spring Boot 2.X 集成spring session实现session共享
6.Redis Cluster搭建高可用Redis服务器集群
7.为什么单线程的Redis这么快?
8.一篇文章搞定SpringMVC参数绑定
9.SpringMVC+Mybatis 如何配置多个数据源并切换?


限时领取免费Java相关资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo/Kafka、Hadoop、Hbase、Flink等高并发分布式、大数据、机器学习等技术。

资料传送门:  https://mp.weixin.qq.com/s/u2b_NVNuMuAPE0w4lc45fw

关注下方公众号即可免费领取:

最新文章

  1. Linux网络属性配置
  2. touches 事件捕获不到
  3. delayed ack与nagle&#39;s算法
  4. 文本溢出省略解决笔记css
  5. N种内核注入DLL的思路及实现
  6. MFC学习笔记(一)向模态对话框传递数据
  7. CSS中父元素高度没有随子元素高度的改变而改变,应该如何解决?
  8. php没有开启Memcache扩展类时
  9. java 多线程学习笔记
  10. 于win7使用虚拟磁盘隐藏文件
  11. 「LINUX资料」简单实用命令less和vi(三)
  12. 关闭Sublime Text的自动更新的方法
  13. iOS enum 定义与使用
  14. [k8s]k8s内容索引
  15. WPS 2019 多个sheet表拆分成独立的excel文件
  16. HDU-2874-森林求LCA/tarjan
  17. robot framework-databaselibaray库使用(python)
  18. 那些年,追寻JMeter的足迹,免费送&hellip;&hellip;
  19. spring+hibernate 整合异常 Class &#39;org.apache.commons.dbcp.BasicDataSource&#39; not found
  20. python redis 的基本操作指令

热门文章

  1. 如何在VMware12中安装centos6.7系统
  2. 【Spring源码解析】—— 策略模式在Spring中的应用
  3. 基于STM32之UART串口通信协议(一)详解
  4. 浅入深出Vue:注册
  5. java 带静态域的导出类创建时都发生了什么?
  6. 使用Task实现非阻塞式的I/O操作
  7. [记录]python的简单协程框架(回调+时间循环+select)
  8. TF项目实战(基于SSD目标检测)——人脸检测1
  9. kafka学习(二)-------- 什么是Kafka
  10. c语言进阶7-结构体