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. IT兄弟连 Java语法教程 流程控制语句 控制循环结构1

    Java语言没有提供goto语句来控制程序的跳转,这种做法提高了程序流程控制的可读性,但降低了程序流程控制的灵活性.为了弥补这种不足,Java提供了continue和break来控制循环结构.除此之外 ...

  2. Java数组拷贝的五种方法

    在Java中有多种方法可以拷贝一个数组,到另外一个数组. 1.循环拷贝 在循环拷贝方法中,只需要利用i,移动指针即可复制所有数组到arrayB中. for(int i=0;i<arrayA.le ...

  3. idea插件备份

  4. mosquitto配置文件

    #配置文件为mosquitto #参见mosquitto.conf(5)了解更多信息. #显示默认值,取消注释以更改. #使用#字符来表示注释,但只有当它是 #第一个字符就行了. #========= ...

  5. python爬取昵称并保存为csv

    代码: import sys import io import re sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030') ...

  6. C# ICloneable,shallow clone,deep clone.

    [Serializable] public class Person:ICloneable { public string Name { get; set; } public int Id { get ...

  7. css文本超出部分用省略号表示

    以前我在面试中遇到过这个问题,当时没答上来,现在回答一下: 1.设置三个属性: overflow:hidden   (超出部分隐藏) white-space:nowrap    (强制不换行) tex ...

  8. 用vue和layui简单写一个响应式数据展示表

    在创建项目之前,先把我们需要的文件打包处理 <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  9. 「SAP技术」 SAP MM MPN物料的采购初探

    「SAP技术」 SAP MM MPN物料的采购初探 1, MPN物料号与我方正常使用料号物料主数据之间的LINK关系维护 MPN料号 14000005 , 我方料号11000250 , 2,采购信息记 ...

  10. 分布式文件管理系统HDFS

    Hadoop 分布式文件管理系统HDFS可以部署在廉价硬件之上,能够高容错. 可靠地存储海量数据(可以达到TB甚至PB级),它还可以和Yam中的MapReduce 编程模型很好地结合,为应用程序提供高 ...