@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

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

Spring条件注解@Conditional的更多相关文章

  1. Spring Boot实战笔记(八)-- Spring高级话题(条件注解@Conditional)

    一.条件注解@Conditional 在之前的学习中,通过活动的profile,我们可以获得不同的Bean.Spring4提供了一个更通用的基于条件的Bean的创建,即使用@Conditional注解 ...

  2. [读书笔记] 二、条件注解@Conditional,组合注解,元注解

    一.条件注解@Conditional,组合注解,元注解 1. @Conditional:满足特定条件创建一个Bean,SpringBoot就是利用这个特性进行自动配置的. 例子: 首先,两个Condi ...

  3. Spring_总结_04_高级配置(二)_条件注解@Conditional

    一.前言 本文承接上一节:Spring_总结_04_高级配置(一)之Profile 在上一节,我们了解到 Profile 为不同环境下使用不同的配置提供了支持,那么Profile到底是如何实现的呢?其 ...

  4. 条件注解@Conditional

    通过活动的profile,可以获得不同的Bean.Spring4提供了一个更通用的基于条件的Bean的创建,即使用@Conditonal注解 @Conditional根据满足某一个特定条件创建一个特定 ...

  5. springboot自动装配(3)---条件注解@Conditional

    之前有说到springboot自动装配的时候,都是去寻找一个XXXAutoConfiguration的配置类,然而我们的springboot的spring.factories文件中有各种组件的自动装配 ...

  6. Spring知识点回顾(06)Profile 和 条件注解 @Conditional

    1.设定环境中的active profiles 如:DispatcherServerlet的init-param spring.profiles.active=production spring.pr ...

  7. SpringBoot条件注解@Conditional

    最近项目中使用到了关于@Conditional注解的一些特性,故写此文记录一下 @Conditional是啥呀? @Conditional注解是个什么东西呢,它可以根据代码中设置的条件装载不同的bea ...

  8. 通过条件注解@Conditional细粒度的选择bean实例

    在进行spring进行开发时,当某个接口有多种实现方式并且我们只想让一种生效时,比如声明如下一个接口和两个实现: public interface LanggageService { String s ...

  9. JavaEE开发之Spring中的条件注解组合注解与元注解

    上篇博客我们详细的聊了<JavaEE开发之Spring中的多线程编程以及任务定时器详解>,本篇博客我们就来聊聊条件注解@Conditional以及组合条件.条件注解说简单点就是根据特定的条 ...

随机推荐

  1. K8s集群部署(三)------ Node节点部署

    之前的docker和etcd已经部署好了,现在node节点要部署二个服务:kubelet.kube-proxy. 部署kubelet(Master 节点操作) 1.二进制包准备 [root@k8s-m ...

  2. 新手如何学python?

    在学习Python前,你应该规划好自己的学习方向,毕竟Python的方向比较多,比如: web开发 爬虫 自动化开发(运维,测试).脚本开发 大数据(数据挖掘,数据分析) 人工智能.机器学习 选择好自 ...

  3. 并发编程-concurrent指南-ReadWriteLock

    ReadWriteLock也是一个接口,在它里面只定义了两个方法: public interface ReadWriteLock { /** * Returns the lock used for r ...

  4. HDU 4462:Scaring the Birds(暴力枚举+状态压缩)

    http://acm.hdu.edu.cn/showproblem.php?pid=4462 题意:有一个n*n的地图,有k个空地可以放稻草人,给出每个空地可以放的稻草人属性,属性中有个R代表这个位置 ...

  5. Flags Over Objects

    The Flags Over Objects anti-pattern occurs when behavior is written outside of an object by inspecti ...

  6. OSPF 单区域实验

    实验拓扑 实验需求 按照图示配置 IP 地址 按照图示分区域配置 OSPF ,实现全网互通 为了路由结构稳定,要求路由器使用环回口作为 Router-id 实验步骤 每台路由器都要将本地的所有直连网段 ...

  7. [Lydsy2017年4月月赛]抵制克苏恩题解

    考试的时候以为就是简单的概率期望题,考完后知道是简单的概率期望DP题,完美爆零. 这道题数据范围很小,很容易让人想到状压,不过貌似没什么可压的.那么只能说明这道题复杂度很高了,状态数组f[o][i][ ...

  8. 彻底搞清楚c#中的委托和事件

    一.什么是委托呢? 听着名字挺抽象,确实不好理解.面试官最喜欢考察这个,而且更喜欢问:“委托和事件有何异同?”.如果对一些知识点没有想明白,那么很容易被绕进去.研究任何事物,我们不妨从它的定义开始,委 ...

  9. 获取一个整数所有的质因数(C语言实现)

    一.题目要求 1. 用户输入任意一个整数,要求程序输出此整数所有的质因数: 2. 用户可以反复输入,直至输入字符'q'退出程序. 二.分析 质因数的概念大家可以问度娘. 题目关键有几个要点,分析透了这 ...

  10. openstack-neutron基本的网络类型以及分析

    [概述] Neutron是OpenStack中负责提供网络服务的组件,基于软件定义网络的思想,实现了网络虚拟化下的资源管理,即:网络即服务. [功能] ·二层交换 Neutron支持多种虚拟交换机,一 ...