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

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

在进行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);
  }
}
复制代码


输出结果:


05266e4ffab347c68908c90fe21472ff~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


三个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);
  }
}
复制代码


f0d3e27a07ca4123bbb80f6f9e96fdd2~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


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


53e89aa39a5e443eb8325b2f00cf3f40~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


微信截图_20220517203647.png


@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,则所有组件都不会注入进容器。


f0d3e27a07ca4123bbb80f6f9e96fdd2~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


微信截图_20220517203728.png


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

目录
相关文章
|
16天前
|
XML Java 数据格式
SpringBoot入门(8) - 开发中还有哪些常用注解
SpringBoot入门(8) - 开发中还有哪些常用注解
36 0
|
1月前
|
Java Spring
在使用Spring的`@Value`注解注入属性值时,有一些特殊字符需要注意
【10月更文挑战第9天】在使用Spring的`@Value`注解注入属性值时,需注意一些特殊字符的正确处理方法,包括空格、引号、反斜杠、新行、制表符、逗号、大括号、$、百分号及其他特殊字符。通过适当包裹或转义,确保这些字符能被正确解析和注入。
|
23天前
|
XML JSON Java
SpringBoot必须掌握的常用注解!
SpringBoot必须掌握的常用注解!
45 4
SpringBoot必须掌握的常用注解!
|
17天前
|
负载均衡 算法 Java
除了 Ribbon,Spring Cloud 中还有哪些负载均衡组件?
这些负载均衡组件各有特点,在不同的场景和需求下,可以根据项目的具体情况选择合适的负载均衡组件来实现高效、稳定的服务调用。
39 5
|
24天前
|
存储 缓存 Java
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
80 2
|
24天前
|
JSON Java 数据库
SpringBoot项目使用AOP及自定义注解保存操作日志
SpringBoot项目使用AOP及自定义注解保存操作日志
35 1
|
19天前
|
存储 安全 Java
springboot当中ConfigurationProperties注解作用跟数据库存入有啥区别
`@ConfigurationProperties`注解和数据库存储配置信息各有优劣,适用于不同的应用场景。`@ConfigurationProperties`提供了类型安全和模块化的配置管理方式,适合静态和简单配置。而数据库存储配置信息提供了动态更新和集中管理的能力,适合需要频繁变化和集中管理的配置需求。在实际项目中,可以根据具体需求选择合适的配置管理方式,或者结合使用这两种方式,实现灵活高效的配置管理。
13 0
|
1月前
|
存储 Java 数据管理
强大!用 @Audited 注解增强 Spring Boot 应用,打造健壮的数据审计功能
本文深入介绍了如何在Spring Boot应用中使用`@Audited`注解和`spring-data-envers`实现数据审计功能,涵盖从添加依赖、配置实体类到查询审计数据的具体步骤,助力开发人员构建更加透明、合规的应用系统。
|
2月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
1月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
179 2
下一篇
无影云桌面