一文了解@Conditional注解说明和使用

目录

    • @Contidional 介绍

      • Condition 接口
      • Spring @Conditional注解实例
    • @Conditional 与@Profile 的对比

? @Conditional:Spring4.0 介绍了一个新的注解@Conditional,它的逻辑语义可以作为"If…then…else…"来对bean的注册起作用。

@Contidional 介绍

? Conditional 是由 SpringFramework 提供的一个注解,位于 org.springframework.context.annotation 包内,定义如下。

package org.springframework.context.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Conditional {

    Class<? extends Condition>[] value();

}

? SpringBoot 模块大量的使用@Conditional 注释,我们可以将Spring的@Conditional注解用于以下场景:

  • 可以作为类级别的注解直接或者间接的与@Component相关联,包括@Configuration类;
  • 可以作为元注解,用于自动编写构造性注解;
  • 作为方法级别的注解,作用在任何@Bean方法上。

Condition 接口

? 我们需要一个类实现Spring提供的Condition接口,它会匹配@Conditional所符合的方法,然后我们可以使用我们在@Conditional注解中定义的类来检查。

public interface Condition {
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

Spring @Conditional注解实例

作用在方法上

? 先来看一个简单一些的示例,我们假设有三个角色老师Teacher、学生Student和父母Parent,三种环境Linux、Windows和MacOSX,如果是Linux环境,就注册Teacher,如果是Windows环境就注册Parent,如果是Mac 环境就注册Student。代码示例如下:

  • 首先创建Teacher和Student对象,没有任何的属性和方法,只是一个空类
//如果当前工程运行在Windows系统下,就注册Student
public class Student {}

//如果当前工程运行在Linux系统下,就注册Teacher
public class Teacher {}

// 如果是Mac OSX 系统,就注册Parent
public class Parent {}
  • 创建一个LinuxCondition和一个WindowsCondition,LinuxCondition能够匹配Linux环境,WindowsCondition能够匹配Windows环境,MacOSX 系统匹配mac环境。
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.stereotype.Component;

public class LinuxCondition implements Condition {

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            // 获取系统环境的属性
          String systemName = context.getEnvironment().getProperty("os.name");
          if(systemName.contains("Linux")){
              return true;
          }
          return false;
    }
}

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
//自定义一个判断条件
public class WindowsCondition implements Condition {

    /*
     * ConditionContext context: spring容器上下文环境
     * AnnotatedTypeMetadata metadata :@Conditional修饰类型信息
     */
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

           String systemName = context.getEnvironment().getProperty("os.name");
           if(systemName.contains("Windows")){
               return true;
           }
        return false;
    }

}

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class OsxCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String property = context.getEnvironment().getProperty("os.name");
        if(property.equals("Mac OS X")){
            return true;
        }
        return false;
    }
}
  • 下面来新建匹配注册环境,如果系统是Linux环境,就注册Teacher,如果系统是Windows,就注册Parent,如果是Mac 系统,就注册Student
import com.spring.condition.beans.Parent;
import com.spring.condition.beans.Student;
import com.spring.condition.beans.Teacher;
import com.spring.condition.util.LinuxCondition;
import com.spring.condition.util.OsxCondition;
import com.spring.condition.util.WindowsCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Conditional(OsxCondition.class)
    @Bean
    public Student student(){
        return new Student();
    }

    @Conditional(LinuxCondition.class)
    @Bean
    public Teacher teacher(){
        return new Teacher();
    }

    @Conditional(WindowsCondition.class)
    @Bean
    public Parent parent(){
        return new Parent();
    }
}
  • 新建测试类进行测试
import com.spring.condition.config.AppConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ConditionTest {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        String[] names = context.getBeanDefinitionNames();
        for(String name : names){
            System.out.println("name = " + name);
        }
    }
}

由输出可以看出,name = student 被输出到控制台,也就是说,我当前所用的系统环境是MacOSX环境,所以注册的是OSXCondition,也就是student的bean。

手动设置系统环境

也可以进行手动修改vm.options,把当前的系统环境变为Linux 或者Windows,以Idea为例:

Edit Configurations中找到vm.options 选项,把系统环境改为 Linux,如下:

然后重新启动测试,发现Teacher 被注入进来了,修改当前环境为Windows,观察Parent也被注入进来并输出了。

作用在类上

? @Conditional 注解可以作用在类上,表示此类下面所有的bean满足条件后都可以进行注入,通常与@Configuration注解一起使用。

  • 新建一个AppClassConfig,在类上标注@Conditional()注解,并配置相关bean,如下:
@Configuration
@Conditional(value = OsxCondition.class)
// 修改config,如果满足OsxCondition环境的话,就把student,parent,teacher都注册进来
public class AppClassConfig {

    @Bean
    public Student student(){
        return new Student();
    }

    @Bean
    public Teacher teacher(){
        return new Teacher();
    }

    @Bean
    public Parent parent(){
        return new Parent();
    }
}

上文表示如果是OsxCondition.class 的话,就注册student、teacher、parent

  • 测试类不用修改,直接用原测试类进行测试,发现student、 teacher、 parent 都被注册进来了

多个条件类

? 因为@Conditional注解的value 方法默认传递一个数组,所以可以接受多个condition,为了测试如下情况,

新建一个 TestCondition类,如下:

// 单纯为了测试
public class TestCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 返回false,表示不匹配
        return false;
    }
}

修改一下AppClassConfig

@Configuration
@Conditional(value = {OsxCondition.class,TestCondition.class})
// 修改config,如果满足OsxCondition环境的话,就把student,parent,teacher都注册进来
public class AppClassConfig {

    @Bean
    public Student student(){
        return new Student();
    }

    @Bean
    public Teacher teacher(){
        return new Teacher();
    }

    @Bean
    public Parent parent(){
        return new Parent();
    }

}

也就是给@Conditional 多加了一个参数 TestCondition.class

启动之前的测试类,发现上述的bean都没有注入,也就是说,只有在满足OsxCondition.class 和 TestCondition.class 都为true的情况下,才会注入对应的bean,修改TestCondition.class的matches方法的返回值为true,重新观察返回结果,发现上述bean都被注入了。

@Conditional 与@Profile 的对比

? @Spring3.0 也有一些和@Conditional 相似的注解,它们是Spring SPEL 表达式和Spring Profiles 注解 Spring4.0的@Conditional 注解要比@Profile 注解更加高级。@Profile 注解用来加载应用程序的环境。@Profile注解仅限于根据预定义属性编写条件检查。 @Conditional注释则没有此限制。

? Spring中的@Profile 和 @Conditional 注解用来检查"If…then…else"的语义。然而,Spring4 @Conditional是@Profile 注解的更通用法。

  • Spring 3中的 @Profiles仅用于编写基于Environment变量的条件检查。 配置文件可用于基于环境加载应用程序配置。
  • Spring 4 @Conditional注解允许开发人员为条件检查定义用户定义的策略。 @Conditional可用于条件bean注册。

文章参考:

https://blog.csdn.net/xcy1193068639/article/details/81491071

原文地址:https://www.cnblogs.com/cxuanBlog/p/10960575.html

时间: 2024-11-02 13:13:25

一文了解@Conditional注解说明和使用的相关文章

spring in action学习笔记七:@Conditional注解的用法

@Profile注解是@Conditional注解的一个例子.即@Profile也是用@Conditional注解来实现的. 必须让条件实现Condition这个接口. 下面的案例讲如果环境中有magic这个属性,则能通过条件,spring会创建bean.反之如果环境中没有magic这个属性,则不能通过条件,spring就不会创建bean,会报错. 案例的代码如下: MagicBean的代码如下: 1 package com.advancedWiring.conditionalBeans; 2

020 使用@Conditional注解完成条件注入

一 .概述 在spring之中提供@Conditional注解完成条件注入. 我们可以实现特定的接口,完成配置类可以根据条件进行Bean的创建. 二 .测试 public abstract class OS { protected String name; public String getName() { return this.name; } } class Windows extends OS { public Windows() { super.name = "windows"

Spring中的@conditional注解

今天主要从以下几方面来介绍一下@Conditional注解 @Conditional注解是什么 @Conditional注解怎么使用 1,@Conditional注解是什么 @Conditional注解是可以根据一些自定义的条件动态的选择是否加载该bean到springIOC容器中去,如果看过springBoot源码的同学会发现,springBoot中大量使用了该注解 2,@Conditional注解怎么使用 查看@Conditional源码你会发现它既可以作用在方法上,同时也可以作用在类上,源

SpringBoot(15)—@Conditional注解

SpringBoot(15)-@Conditional注解 作用 @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件的才给容器注册Bean. 一.概述 1.@Conditional注解定义 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Conditional { Clas

Spring @Conditional注解的使用

Spring Boot的强大之处在于使用了Spring 4框架的新特性:@Conditional注释,此注释使得只有在特定条件满足时才启用一些配置. 下面来介绍如何使用Condition 首先写一个类 package com.test.spring; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; imp

Spring条件注解@Conditional

@Conditional 基于条件的Bean的创建,根据满足某一个特定条件创建特定的Bean,通过实现Condition接口,并重写matches接口来构造判断条件. 下面的实例通过将以不同操作系统作为条件,我们将通过实现Condition接口,并重写其matchess方法来构造判断条件.若在Windows系统下运行程序,则输出列表命令为dir:若在Linux操作系统下运行程序,则输出列表命令为ls1.判断条件定义(1)判断Windows的条件 package com.lwh.highlight

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

一.前言 本文承接上一节:Spring_总结_04_高级配置(一)之Profile 在上一节,我们了解到 Profile 为不同环境下使用不同的配置提供了支持,那么Profile到底是如何实现的呢?其实Profile正是通过条件注解来实现的. 条件注解的应用场景举例: (1)希望一个或多个 bean 只有在应用的类路径下包含特定的库时才创建 (2)希望某个bean只有当另外某个特定bean也声明了之后才创建 (3)希望只有某个特定的环境变量设置之后,才会创建某个bean 上述场景能让我们联想到s

SpringBoot条件注解@Conditional

@Conditional是啥呀? @Conditional注解是个什么东西呢,它可以根据代码中设置的条件装载不同的bean,比如说当一个接口有两个实现类时,我们要把这个接口交给Spring管理时通常会只选择实现其中一个实现类,这个时候我们总不能使用if-else吧,所以这个@Conditional的注解就出现了. 我怎么用它呢? 在SpringBoot中,@Conditional注解并不是孤军奋斗,它们是一个家族,我们来看一下它们其中的几个成员,又都是怎么用的 @ConditionalOnBea

Spring5源码深度分析(二)之理解@Conditional,@Import注解

代码地址:https://github.com/showkawa/spring-annotation/tree/master/src/main/java/com/brian 1.源码分析二主要分析的内容 1.使用@Condition多条件注册bean对象[email protected]注解快速注入第三方bean对象[email protected] 开启原理4.基于ImportBeanDefinitionRegistrar注册bean5.基于FactoryBean注册bean对象 1.使用@C