Article for instructions and usage notes @Conditional

@Conditional: Spring4.0 introduced a new comment @Conditional, its logic semantics as "If ... then ... else ..." to register the work of the bean.

@Contidional Introduction

Conditional annotation is provided by a SpringFramework, located within org.springframework.context.annotation package, as defined below.

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 module lot of use @Conditional comments, we can @Conditional Spring's annotation for the following scenarios:

  • A class-level annotation may directly or indirectly associated with @Component, comprising @Configuration class;
  • As annotation element, configured for automatically written annotations;
  • As a method level annotations acting on any @Bean method.

Condition Interface

We need a class that implements the Condition interface provided by Spring, it will match the method @Conditional comply, then we can use the class we defined in @Conditional annotation to check.

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

Spring @Conditional annotated examples

Role in the method

First look at a simpler example, we assume that there are three roles the teacher Teacher, students and parents Student Parent, three environments Linux, Windows and MacOSX, if a Linux environment, register Teacher, if a Windows environment on registration Parent, If you're a Mac environment Register Student. Code examples are as follows:

  • First create Teacher and Student objects, without any of the properties and methods, just an empty class
//如果当前工程运行在Windows系统下,就注册Student
public class Student {}

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

// 如果是Mac OSX 系统,就注册Parent
public class Parent {}
  • Create a LinuxCondition and a WindowsCondition, LinuxCondition able to match the Linux environment, WindowsCondition able to match the Windows environment, MacOSX system matching mac environment.
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;
    }
}
  • Sign up below to create a new environment to match, if the system is Linux environment, register Teacher, if the system is Windows, register Parent, if a Mac, register 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();
    }
}
  • New Test class test
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);
        }
    }
}

As can be seen from the output, name = student is output to the console, that is to say, my current system environment is used MacOSX environment, so registration is OSXCondition, is the student of bean.

Manually set the system environment

It can also be modified manually vm.options , the current system environment into Linux or Windows, with Idea as an example:

In Edit Configurationsfound in vm.options option, the system environment changed to Linux, as follows:

Then restart the test and found to be injected Teacher came, modify the current environment for Windows, observe Parent also be injected in and output.

In the class on the role of

@Conditional annotation may act on the class represented by the following bean all such conditions can be satisfied after the injection, and is typically used with annotations @Configuration.

  • A new AppClassConfig, marked on the class @Conditional () annotations, and configure the bean, as follows:
@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();
    }
}

He said that if the above is OsxCondition.class then it registered student, teacher, parent

  • Test class without modification, to test the direct use of original test class, found student, teacher, parent are registered came

A plurality of condition classes

Because the value of annotation method @Conditional pass a default array, you can accept multiple for condition Condition, in order to test a case,

A new TestConditioncategories, as follows:

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

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

edit a bitAppClassConfig

@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();
    }

}

That is an argument to pay more @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

Guess you like

Origin www.cnblogs.com/cxuanBlog/p/10960575.html
Recommended