Spring注解(四):@Conditional根据条件注册组件

987 阅读4分钟

作者的其他平台:

| CSDN:blog.csdn.net/qq_41153943

| 掘金:juejin.cn/user/651387…

| 知乎:www.zhihu.com/people/1024…

| GitHub:github.com/JiangXia-10…

本文大概1704字,建议阅读10分钟

在进行spring注解开发时,如果对于某个bean生成了多个实例,在进行组件注册的时候会全部注入到IOC的容器当中,比如:

实体类代码:

package com.xinyi.bean;
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;
  }
  @Override
  public String toString() {
    return "Person [name=" + name + ", age=" + age + "]";
  }
  public Person(String name, Integer age) {
    super();
    this.name = name;
    this.age = age;
  }
  public Person() {
  }
}

配置类代码:

package com.xinyi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.xinyi.bean.Person;
@Configuration
public class MyConfig1 {
  @Bean("Lin Sin")
  public Person person() {
    return new Person("李青",18);
  }
  @Bean("Yasuo")
  public Person person1() {
    return new Person("亚索",23);
  }
  @Bean("Zed")
  public Person person2() {
    return new Person("劫",32);
  }
}

测试类代码:

package com.xinyi.test;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.xinyi.bean.Person;
import com.xinyi.config.MyConfig1;


public class IOCTest {
  @Test
  public void test3() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig1.class);
    String[] names = applicationContext.getBeanNamesForType(Person.class);
    for(String name:names) {
      System.out.println(name);
    }
        Map<String, Person> persons = applicationContext.getBeansOfType(Person.class);
    System.out.println(persons);
  }
}

输出结果:

图片

三个bean的实例都被注入到IOC容器之中,但是在开发过程中并非所有的bean实例都是需要的,Conditional注解则能够根据不同的需求注入不同的bean实例,@Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean,@Conditional注解的源码如下:

//此注解可以标注在类和方法上
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
  /**
   * All {@link Condition Conditions} that must {@linkplain Condition#matches match}
   * in order for the component to be registered.
   */
  Class<? extends Condition>[] value();


}

@Conditional注解既可以使用在类上,也可以使用在方法上。根据Conditional 注解的源码,在Conditional 注解的参数中需要接受一个Condition(条件)数组,实现Condition 接口的matches方法。

@FunctionalInterface
public interface Condition {


  /**
   * Determine if the condition matches.
   * @param context the condition context
   * @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
   * or {@link org.springframework.core.type.MethodMetadata method} being checked
   * @return {@code true} if the condition matches and the component can be registered,
   * or {@code false} to veto the annotated component's registration
   */
  boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);


}

通过获取计算机系统的环境注入不同的bean实例,Condition1判断本地系统为windows系统,Condition2判断本地系统如果Linux系统:

package com.xinyi.condition;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
//判断是否是windows系统
public class Condition1 implements Condition{
  /**
   * ConditionContext:判断条件能使用的上下文,这里是角色
   * AnnotatedTypeMetadata:当前标注了Condition注解的注释信息
   */
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    // 判断角色是否是打野
    //1.能够获取到ioc容器使用的beanfactory
    ConfigurableBeanFactory beanFactory = context.getBeanFactory();
    //2、获取类加载器
    ClassLoader loader = context.getClassLoader();
    //3、获取当前环境信息
    Environment environment=context.getEnvironment();
    //4、获取bean定义的注册类
    BeanDefinitionRegistry registry = context.getRegistry();
    String property = environment.getProperty("os.name");
    if(property.contains("Windows")) {
      return true;
    }
    return false;
  }
}
package com.xinyi.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
//判断是否是linux系统
public class Condition2 implements Condition {
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    Environment environment = context.getEnvironment();
    String property = environment.getProperty("os.name");
    if(property.contains("linux")) {
      return true;
    }
    return false;
  }
  
}

给person和person1使用@Conditional注解,并且分别赋值Conditional1和Conditional2,由于本地系统是window10,所以根据Conditional1的条件Lin Sin和未加任何条件的Zed被注入进容器。

package com.xinyi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import com.xinyi.bean.Person;
import com.xinyi.condition.Condition1;
import com.xinyi.condition.Condition2;
@Configuration
public class MyConfig1 {
  //@Scope("prototype")
  //默认单实例
  @Bean("Lin Sin")
  @Lazy
  @Conditional(Condition1.class)
  public Person person() {
    //System.out.println("IOC容器中注入person实例");
    return new Person("李青",18);
  }
  
  @Conditional(Condition2.class)
  @Bean("Yasuo")
  public Person person1() {
    return new Person("亚索",23);
  }
  @Bean("Zed")
  public Person person2() {
    return new Person("劫",32);
  }
}

图片

然后右键 run as—>run configurations----->选择Arguments在vm arguments中输入-Dos.name=linux,将运行时的系统环境设为linux系统,则Conditional2的条件Yasuo和未加任何条件的Zed被注入进容器。

图片

图片

@Conditional(Condition1.class)不仅可以作用在方法上还能作用在类上,作用在类上则表示如果满足条件,则类中的所有bean注册都能生效,反之都不能生效。

package com.xinyi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import com.xinyi.bean.Person;
import com.xinyi.condition.Condition1;
import com.xinyi.condition.Condition2;
@Configuration
@Conditional(Condition1.class)
public class MyConfig1 {
  
  //@Scope("prototype")
  //默认单实例
  @Bean("Lin Sin")
  @Lazy
  @Conditional(Condition1.class)
  public Person person() {
    //System.out.println("IOC容器中注入person实例");
    return new Person("李青",18);
  }
  
  //@Conditional(Condition2.class)
  @Bean("Yasuo")
  public Person person1() {
    return new Person("亚索",23);
  }
  
  @Bean("Zed")
  public Person person2() {
    return new Person("劫",32);
  }
}

所有的bean都注入到ioc容器中,再修改计算机环境参数,@Conditional注解条件改为linux,则所有组件都不会注入进容器。

图片

图片

以上就是使用@Conditional注解根据条件进行组件的注入。

最后欢迎关注公众号:1024笔记,免费获取海量学习资源(涵盖视频、源码、文档)!

相关推荐: