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注解根据条件进行组件的注入。

目录
相关文章
|
3月前
|
缓存 监控 Java
SpringBoot @Scheduled 注解详解
使用`@Scheduled`注解实现方法周期性执行,支持固定间隔、延迟或Cron表达式触发,基于Spring Task,适用于日志清理、数据同步等定时任务场景。需启用`@EnableScheduling`,注意线程阻塞与分布式重复问题,推荐结合`@Async`异步处理,提升任务调度效率。
600 128
|
2月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
430 2
|
3月前
|
Java 测试技术 数据库
使用Spring的@Retryable注解进行自动重试
在现代软件开发中,容错性和弹性至关重要。Spring框架提供的`@Retryable`注解为处理瞬时故障提供了一种声明式、可配置的重试机制,使开发者能够以简洁的方式增强应用的自我恢复能力。本文深入解析了`@Retryable`的使用方法及其参数配置,并结合`@Recover`实现失败回退策略,帮助构建更健壮、可靠的应用程序。
439 1
使用Spring的@Retryable注解进行自动重试
|
3月前
|
XML Java 数据格式
常用SpringBoot注解汇总与用法说明
这些注解的使用和组合是Spring Boot快速开发和微服务实现的基础,通过它们,可以有效地指导Spring容器进行类发现、自动装配、配置、代理和管理等核心功能。开发者应当根据项目实际需求,运用这些注解来优化代码结构和服务逻辑。
318 12
|
3月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
201 0
探索Spring Boot的@Conditional注解的上下文配置
|
3月前
|
智能设计 Java 测试技术
Spring中最大化@Lazy注解,实现资源高效利用
本文深入探讨了 Spring 框架中的 `@Lazy` 注解,介绍了其在资源管理和性能优化中的作用。通过延迟初始化 Bean,`@Lazy` 可显著提升应用启动速度,合理利用系统资源,并增强对 Bean 生命周期的控制。文章还分析了 `@Lazy` 的工作机制、使用场景、最佳实践以及常见陷阱与解决方案,帮助开发者更高效地构建可扩展、高性能的 Spring 应用程序。
153 0
Spring中最大化@Lazy注解,实现资源高效利用
|
3月前
|
Java 测试技术 编译器
@GrpcService使用注解在 Spring Boot 中开始使用 gRPC
本文介绍了如何在Spring Boot应用中集成gRPC框架,使用`@GrpcService`注解实现高效、可扩展的服务间通信。内容涵盖gRPC与Protocol Buffers的原理、环境配置、服务定义与实现、测试方法等,帮助开发者快速构建高性能的微服务系统。
655 0
|
缓存 负载均衡 监控
Spring Cloud 五大组件 简介 Eureka、Ribbon、Hystrix、Feign和Zuul
Spring Cloud 五大组件 简介 Eureka、Ribbon、Hystrix、Feign和Zuul
2229 0
|
负载均衡 算法 网络协议
Spring Cloud 五大核心组件解析之Ribbon简介
Spring Cloud 五大核心组件解析之Ribbon简介
|
Java 容器 Spring
Spring 三大基础组件简介
    一,Bean,Core,Context关系   在Spring的各种组件中,Bean,Core,Context算是基础组件(ExpressionLanguage表达式支持, 这个主要就是用来支持一些spring XML配置文件表达式 和 注解中一些表达式解析,让配置有动态特性,spring早期的版本是没有这货的,不算是特别必须的, 特别核心的东西,只是为了灵活性加的),在Core container这一层构建起了整个Spring的骨骼架构。
1659 0

热门文章

最新文章