Spring注解之@Conditional

【1】@Conditional介绍

​ @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean。

​ @Conditional源码:

//此注解可以标注在类和方法上
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}

​ 从代码中可以看到,需要传入一个Class数组,并且需要继承Condition接口:

public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}

​ Condition是个接口,需要实现matches方法,返回true则注入bean,false则不注入。

【2】@Conditional示例

​ 首先,创建Person类:

public class Person {

    private String name;
private Integer age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public Person(String name, Integer age) {
this.name = name;
this.age = age;
} @Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}

​ 创建MyConfig类,用于配置两个Person实例并注入,一个是Bill Gates,一个是linus。

@Configuration
public class MyConfig { @Bean(name = "bill")
public Person person1(){
return new Person("Bill Gates",62);
} @Bean("linus")
public Person person2(){
return new Person("Linus",48);
}
}

​ 写一个测试类,测试是否注入成功

public class ConditionalTest {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class); @Test
public void test1(){
Map<String, Person> map = applicationContext.getBeansOfType(Person.class);
System.out.println(map);
}
}
/**测试结果
{bill=Person{name='Bill Gates',age=62},linus=Person{name='Linus',age='48'}}
*/

​ 这是一个简单的例子,现在问题来了,如果我想根据当前操作系统来注入Person实例,windows下注入bill,linux下注入linus,怎么实现呢?

​ 这就需要我们用到@Conditional注解了,前言中提到,需要实现Condition接口,并重写方法来自定义match规则。

​ 首先,创建一个WindowsCondition类:

public class WindowsCondition implements Condition {

    /**
* @param conditionContext:判断条件能使用的上下文环境
* @param annotatedTypeMetadata:注解所在位置的注释信息
* */
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//获取ioc使用的beanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//获取类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
//获取当前环境信息
Environment environment = conditionContext.getEnvironment();
//获取bean定义的注册类
BeanDefinitionRegistry registry = conditionContext.getRegistry(); //获得当前系统名
String property = environment.getProperty("os.name");
//包含Windows则说明是windows系统,返回true
if (property.contains("Windows")){
return true;
}
return false;
}
}

​ 接着,创建LinuxCondition类:

public class LinuxCondition implements Condition {

    @Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { Environment environment = conditionContext.getEnvironment(); String property = environment.getProperty("os.name");
if (property.contains("Linux")){
return true;
}
return false;
}
}

​ 修改MyConfig:

@Configuration
public class MyConfig { //只有一个类时,大括号可以省略
//如果WindowsCondition的实现方法返回true,则注入这个bean
@Conditional({WindowsCondition.class})
@Bean(name = "bill")
public Person person1(){
return new Person("Bill Gates",62);
} //如果LinuxCondition的实现方法返回true,则注入这个bean
@Conditional({LinuxCondition.class})
@Bean("linus")
public Person person2(){
return new Person("Linus",48);
}
}

标注在方法上:

​ 修改测试程序,开始测试:

public class ConditionalTest {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class); @Test
public void test1(){
String osName = applicationContext.getEnvironment().getProperty("os.name");
System.out.println("当前系统为:" + osName);
Map<String, Person> map = applicationContext.getBeansOfType(Person.class);
System.out.println(map);
}
}
/**测试结果
当前系统为:Windows 10
{bill=Person{name='Bill Gates',age=62}}
*/

一个方法只能注入一个bean实例,所以@Conditional标注在方法上只能控制一个bean实例是否注入

标注在类上:

@Configuration
@Conditional({WindowsCondition.class})
public class MyConfig { //只有一个类时,大括号可以省略
//如果WindowsCondition的实现方法返回true,则注入这个bean
@Bean(name = "bill")
public Person person1(){
return new Person("Bill Gates",62);
} //如果LinuxCondition的实现方法返回true,则注入这个bean
@Bean("linus")
public Person person2(){
return new Person("Linus",48);
}
}

一个类中可以注入很多实例,@Conditional标注在类上就决定了一批bean是否注入。

二、Spring注解之@Conditional的更多相关文章

  1. Spring 注解驱动(二)Servlet 3.0 注解驱动在 Spring MVC 中的应用

    Spring 注解驱动(二)Servlet 3.0 注解驱动在 Spring MVC 中的应用 Spring 系列目录(https://www.cnblogs.com/binarylei/p/1019 ...

  2. Spring 注解(二)注解工具类 AnnotationUtils 和 AnnotatedElementUtils

    Spring 注解(二)注解工具类 AnnotationUtils 和 AnnotatedElementUtils Spring 系列目录(https://www.cnblogs.com/binary ...

  3. Spring Boot 二十个注解

    Spring Boot 二十个注解 占据无力拥有的东西是一种悲哀. Cold on the outside passionate on the insede. 背景:Spring Boot 注解的强大 ...

  4. 【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解

    写在前面 最近,二狗子入职了新公司,新入职的那几天确实有点飘.不过慢慢的,他发现他身边的人各个身怀绝技啊,有Spring源码的贡献者,有Dubbo源码的贡献者,有MyBatis源码的贡献者,还有研究A ...

  5. Spring 注解(二)注解工具类

    本文转载自Spring 注解(二)注解工具类 导语 首先回顾一下 AnnotationUtils 和 AnnotatedElementUtils 这两个注解工具类的用法: @Test @GetMapp ...

  6. Spring 注解驱动(一)基本使用规则

    Spring 注解驱动(一)基本使用规则 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.基本使用 @Configur ...

  7. spring注解扫描组件注册

    最近对单点系统进行微服务拆分,被各个springboot的组件注册搞得云里雾里的.(有的是通过springboot的自动配置进IOC容器的,有的是自己添加构造方法添加进IOC容器.)决定抽时间将spr ...

  8. Spring注解(生命周期)

    对于上面的知识图解,需要一点一点的研究. 首先核心容器: 控制反转 和 依赖注入 创建工程: maven仓库搜索 spring context  : 引入后 <!-- https://mvnre ...

  9. 006-Spring Boot自动配置-Condition、Conditional、Spring提供的Conditional自动配置

    一.接口Condition.Conditional(原理) 主要提供一下方法 boolean matches(ConditionContext context, AnnotatedTypeMetada ...

随机推荐

  1. Map拼接URL地址

    import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * @Author: hoje * Des ...

  2. WPF 使用动画设置特殊值的方法

    例如设置Visibility属性时: 第一种方式: <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIEleme ...

  3. .net core 中使用 openssl 公钥私钥进行加解密

    这篇博文分享的是 C#中使用OpenSSL的公钥加密/私钥解密 一文中的解决方法在 .net core 中的改进.之前的博文针对的是 .NET Framework ,加解密用的是 RSACryptoS ...

  4. U8 BOM数据结构

    U8 BOM涉及的数据表有四张 bom_bom     BOM资料  该表主要记录BOM表的一些基本信息,版本.创建.审核等信息,不包括任何子件.母件信息:bomid是BOM主键 bom_parent ...

  5. C#使用Emgu CV来进行图片人脸检测

    项目需求:某市级组织考试,在考试前需审核考生采集表中的考生照片是否合格,由于要审核的考生信息采集表有很多,原先进行的是手动人工审核,比较费时费力,审核的要求也很简单,并不判断考生是否是图片本人(身份验 ...

  6. c#中xml增删查改

    /// <summary> /// xml转list /// </summary> /// <typeparam name="T">目标对象&l ...

  7. 盲法介绍及python盲打练习系统

    目录 一:盲打简介与优点 二:如何练习 三:键盘字母排列顺序的口诀 四:python打字练习系统 一:盲打简介与优点   简介:盲打是指打字的时候不用看键盘或看稿打字时的视线不用来回于文稿和键盘之间的 ...

  8. 协议分析中的TCP/IP网络协议

    - 链路层 第一层包含源mac及目的mac,随着传输路径的变化会发生变化,在mac之后,是下层网络协议的类型,图中,下层为IP协议. 在协议解析中,需要关注的是图中type这个字段的内容. - 网络层 ...

  9. apache jmeter 使用

    ======================= 插件 ======================= 在JMeter 中很多东西都是基于插件技术的, 所以扩展性非常好, 比如下面这些东西都是插件: 1 ...

  10. nginx 配置实例-负载均衡

    1.实现效果 (1)浏览器地址栏输入地址 http://www.123.com/edu/a.html,负载均衡效果,平均 8080 和 8081 端口中 2.准备工作 (1)准备两台 tomcat 服 ...