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. 《细说PHP》第四版 样章 第23章 自定义PHP接口规范 11

    23.6  使用第三方接口服务实例 接供服务的第三方接口平台有很多,现在的项目中也经常用到一些第三方接口,如支付宝.微信.短信.邮件接口等,我们需要借助第三方的能力来实现产品的某些功能.如果自己已经掌 ...

  2. GPU跑tf-faster-rcnn demo以及训练自己的数据

    https://blog.csdn.net/qq_39123369/article/details/85245512

  3. [03]使用 VS2019 创建 ASP.NET Core Web 程序

    使用 VS2019 创建 ASP.NET Core Web 程序 本文作者:梁桐铭- 微软最有价值专家(Microsoft MVP) 文章会随着版本进行更新,关注我获取最新版本 本文出自<从零开 ...

  4. pandas 学习 第5篇:DataFrame - 访问数据框

    数据框是用于存储数据的二维结构,分为行和列,一行和一列的交叉位置是一个cell,该cell的位置是由行索引和列索引共同确定的.可以通过at/iat,或loc/iloc属性来访问数据框的元素,该属性后跟 ...

  5. DevExpress的下拉框控件ComboxBoxEdit怎样绑定键值对选项

    场景 DevExpress的下拉框控件ComboBoxEdit控件的使用: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/1028 ...

  6. for与foreach区别

    首先说一下for循环: 格式:for( ; ; ){}; public static void main(String[] args) { List<String> arr = new A ...

  7. 自学_CSS<二>

    CSS CSS(层叠样式表)是用来美化页面用的,可以对页面元素进行更精细的设置,样式主要描述元素的字体颜色.背景颜色.边框等. CSS主要有元素内联.页面嵌入和外部引用三种使用方式.CSS是描述元素的 ...

  8. JavaWeb之JSP & EL & JSTL

    JSP & EL & JSTL JSP Java Server Page 什么是JSP 从用户角度看,就是一个网页.从程序员角度看,就是一个Java类,它继承Servlet,所以可以说 ...

  9. 「SAP技术」SAP MM 事务代码ME17的用法

    SAP MM 事务代码ME17的用法 1,如下采购信息记录需要被归档: PIR号码,5300007816   2, ME12打上删除标记,   3, 事务代码ME17做归档 3.1 创建archive ...

  10. (转载)林轩田机器学习基石课程学习笔记1 — The Learning Problem

    (转载)林轩田机器学习基石课程学习笔记1 - The Learning Problem When Can Machine Learn? Why Can Machine Learn? How Can M ...