SpringBoot(15)—@Conditional注解

SpringBoot(15)—@Conditional注解

作用 @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件的才给容器注册Bean。

一、概述

1、@Conditional注解定义

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    Class<? extends Condition>[] value();
}

2、Condition

我们点进去看后,发现它是一个接口,有一个方法。

@FunctionalInterface
public interface Condition {
    boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}

3、ConditionContext

它持有不少有用的对象,可以用来获取很多系统相关的信息,来丰富条件判断,接口定义如下

public interface ConditionContext {
    /**
     * 获取Bean定义
     */
    BeanDefinitionRegistry getRegistry();
    /**
     * 获取Bean工程,因此就可以获取容器中的所有bean
     */
    @Nullable
    ConfigurableListableBeanFactory getBeanFactory();
    /**
     * environment 持有所有的配置信息
     */
    Environment getEnvironment();
    /**
     * 资源信息
     */
    ResourceLoader getResourceLoader();
    /**
     * 类加载信息
     */
    @Nullable
    ClassLoader getClassLoader();
}

二、案例

需求 根据当前系统环境的的不同实例不同的Bean,比如现在是Mac那就实例一个Bean,如果是Window系统实例另一个Bean。

1、SystemBean

首先创建一个Bean类

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class SystemBean {
    /**
     * 系统名称
     */
    private String systemName;
    /**
     * 系统code
     */
    private String systemCode;
}

2、通过Configuration配置实例化Bean

@Slf4j
@Configuration
public class ConditionalConfig {
    /**
     * 如果WindowsCondition的实现方法返回true,则注入这个bean
     */
    @Bean("windows")
    @Conditional({WindowsCondition.class})
    public SystemBean systemWi() {
        log.info("ConditionalConfig方法注入 windows实体");
        return new SystemBean("windows系统","002");
    }
    /**
     * 如果LinuxCondition的实现方法返回true,则注入这个bean
     */
    @Bean("mac")
    @Conditional({MacCondition.class})
    public SystemBean systemMac() {
        log.info("ConditionalConfig方法注入 mac实体");
        return new SystemBean("Mac ios系统","001");
    }
}

3、WindowsCondition和MacCondition

这两个类都实现了Condition接口, 只有matches方法返回true才会实例化当前Bean

1)WindowsCondition

@Slf4j
public class WindowsCondition implements Condition {
    /**
     * @param conditionContext:判断条件能使用的上下文环境
     * @param annotatedTypeMetadata:注解所在位置的注释信息
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //获取ioc使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader = conditionContext.getClassLoader();
        //获取当前环境信息
        Environment environment = conditionContext.getEnvironment();
        //获取bean定义的注册类
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
        //获得当前系统名
        String property = environment.getProperty("os.name");
        //包含Windows则说明是windows系统,返回true
        if (property.contains("Windows")){
            log.info("当前操作系统是:Windows");
            return true;
        }
        return false;
    }
}

2) MacCondition

@Slf4j
public class MacCondition implements Condition {

   @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Environment environment = conditionContext.getEnvironment();
        String property = environment.getProperty("os.name");
        if (property.contains("Mac")) {
            log.info("当前操作系统是:Mac OS X");
            return true;
        }
        return false;
    }
}

4、测试类测试

/**
 * @author xub
 * @date 2019/6/13 下午10:42
 */
@SpringBootTest(classes = Application.class)
@RunWith(SpringRunner.class)
public class TestConditionOn {

    @Autowired
    private SystemBean windows;
    @Autowired
    private SystemBean mac;

    @Test
    public void test() {
        if (windows != null) {
            System.out.println("windows = " + windows);
        }
        if (mac != null) {
            System.out.println("linux = " + mac);
        }
    }
}

运行结果

通过运行结果可以看出

1、虽然配置两个Bean,但这里只实例化了一个Bean,因为我这边是Mac电脑,所以实例化的是mac的SystemBean

2、注意一点,我们可以看出 window并不为null,而是mac实例化的Bean。说明 只要实例化一个Bean的,不管你命名什么,都可以注入这个Bean。

修改一下

这里做一个修改,我们把ConditionalConfig中的这行代码注释掉。

// @Conditional({WindowsCondition.class})

再运行下代码

通过运行结果可以看出,配置类的两个Bean都已经注入成功了。

注意 当同一个对象被注入两次及以上的时候,那么你在使用当前对象的时候,名称一定要是两个bean名称的一个,否则报错。比如修改为

    @Autowired
    private SystemBean windows;
    @Autowired
    private SystemBean mac;
    @Autowired
    private SystemBean linux;

在启动发现,报错了。

意思很明显,就是上面只实例化成功一个SystemBean的时候,你取任何名字,反正就是把当前已经实例化的对象注入给你就好了。
但是你现在同时注入了两个SystemBean,你这个时候有个名称为linux,它不知道应该注入那个Bean,所以采用了报错的策略。

GitHub源码 https://github.com/yudiandemingzi/SpringBootBlog

项目名称 03-conditional

参考

1、Spring @Conditional注解

只要自己变优秀了,其他的事情才会跟着好起来(中将3)

原文地址:https://www.cnblogs.com/qdhxhz/p/11020434.html

时间: 2024-11-09 20:02:02

SpringBoot(15)—@Conditional注解的相关文章

springboot + shiro 权限注解、请求乱码解决、统一异常处理

springboot + shiro 权限注解.请求乱码解决.统一异常处理 前篇 后台权限管理系统 相关: spring boot + mybatis + layui + shiro后台权限管理系统 springboot + shiro之登录人数限制.登录判断重定向.session时间设置 springboot + shiro 动态更新用户信息 基于前篇,新增功能: 新增shiro权限注解: 请求乱码问题解决: 统一异常处理. 源码已集成到项目中: github源码: https://githu

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

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

springboot 定时任务@Scheduled注解

需要定时器的地方好像还挺多. 之前项目中有用到使用定时器循环订单时间,然后将超时的订单状态更改. springboot的@Scheduled注解能够很快速完成我们需要的定时任务. @Component public class ExampleTimer { SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); /*每100秒执行一次*/ @Scheduled(fixedRate = 100000) public

Spring中的@conditional注解

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

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

目录 @Contidional 介绍 Condition 接口 Spring @Conditional注解实例 @Conditional 与@Profile 的对比 ? @Conditional:Spring4.0 介绍了一个新的注解@Conditional,它的逻辑语义可以作为"If-then-else-"来对bean的注册起作用. @Contidional 介绍 ? Conditional 是由 SpringFramework 提供的一个注解,位于 org.springframew

SpringBoot使用Mybatis注解进行一对多和多对多查询(2)

SpringBoot使用Mybatis注解进行一对多和多对多查询 GitHub的完整示例项目地址kingboy-springboot-data 一.模拟的业务查询 系统中的用户user都有唯一对应的地址信息address,每个用户可以有多量车car,类似如下结构 |-- user |-- address |-- carList |-- car1 |-- car2 二.对应的实体类如下 /省略setter/getter public class Address { private Long id;

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"

springboot整合mybatis(注解)

springboot整合mybatis(注解) 1.pom.xml: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="ht

SpringBoot利用自定义注解实现AOP

SpringBoot利用自定义注解实现AOP java 本文主要讲解利用SpringBoot的自定义注解来实现AOP思想. 在开始所有的操作之前,需要导入aop坐标: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> 如何自定义注解? 实际上注解本