【Spring注解】@Conditional


源码: https://github.com/nieandsun/spring-study

1 Conditional相关注解简介

在Springboot项目里我们可能会在开发中用到好多与Conditional相关的注解,如:

  • @ConditionalOnClass
  • @ConditionalOnBean
  • @ConditionalOnMissingBean
  • @ConditionalOnMissingClass
  • @ConditionalOnProperty

等,其实根据英文我们可以很容易的知道这些注解的意思,但难的是很多时候根本想不起来用。

今天在玩spring源码的时候发现其实spring原生注解里只有 @Conditional这一个注解, 而上面列出来的这些与Conditional相关的注解其实是springboot对其进行扩展的,而且扩展的还挺丰富的,如下图所示:
在这里插入图片描述

2 @Conditional注解的简单使用

本篇主要来介绍一下@Conditional注解的使用。

场景描述: 当服务器以Win环境启动时,向IOC容器中注入xiaoming这个对象,以Linux环境启动时,向IOC容器中注入xiaohong这个对象。

(1) 准备两个Condition对象 — 作为对象注册条件类

  • win环境的注册条件
package com.nrsc.springstudy.c08_Conditional.conditional;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * Description: 该类作为bean的注册条件类,需要实现Condition接口,并实现其matches方法
 */
public class WinCondition implements Condition {

    /***
     *
     * @param context 判断条件能使用的上下文(环境)
     * @param metadata 注释信息
     * @return
     */
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //通过context可以拿到很多信息,如:

//        //可以获取到IOC容器使用的beanFactory
//        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//        //可以获取到类加载器
//        ClassLoader classLoader = context.getClassLoader();
//        //获取bean定义的注册类
//        BeanDefinitionRegistry registry = context.getRegistry();
//        //获取资源加载器
//        ResourceLoader resourceLoader = context.getResourceLoader();

        //todo 如果运行环境为win则返回true
        //获取当前环境信息
        Environment environment = context.getEnvironment();
        //获取当前运行环境的系统名称
        String property = environment.getProperty("os.name");
        if (property.contains("Windows")) {
            return true;
        }
        return false;
    }
}
  • linux环境的注册条件
package com.nrsc.springstudy.c08_Conditional.conditional;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * Description: 该类作为bean的注册条件类,需要实现Condition接口,并实现其matches方法
 */
public class LinuxCondition implements Condition {
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

        //todo 如果运行环境为linux则返回true
        //获取当前环境信息
        Environment environment = context.getEnvironment();
        //获取当前运行环境的系统名称
        String property = environment.getProperty("os.name");
        if (property.contains("linux")) {
            return true;
        }
        return false;
    }
}

(2)利用@Conditional注解实现功能

package com.nrsc.springstudy.c08_Conditional.config;

import com.nrsc.springstudy.c08_Conditional.conditional.LinuxCondition;
import com.nrsc.springstudy.c08_Conditional.conditional.WinCondition;
import com.nrsc.springstudy.domain.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class C08Config {
    /***
     * 注册xiaoming的注册条件使用WinCondition.class
     * @return
     */
    @Conditional(WinCondition.class)
    @Bean("xiaoming")
    public Student student1() {
        System.out.println("给容器中添加小明同学。。。win");
        return new Student("xiaoming", 10);
    }
    /***
     * 注册xiaohong的注册条件使用WLinuxCondition.class
     * @return
     */
    @Conditional(LinuxCondition.class)
    @Bean("xiaohong")
    public Student student2() {
        System.out.println("给容器中添加小红同学。。。lin");
        return new Student("xiaohong", 9);
    }
}

(3) spring 环境启动类

import com.nrsc.springstudy.c08_Conditional.config.C08Config;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test_08_Conditional {

    @Test
    public void test01() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(C08Config.class);
        System.out.println("IOC容器创建完成........");
    }
}

(4) 测试

win系统下运行test01方法,控制台打印结果如下,说明当以win环境启动时,确实只有xiaoming被注册到了IOC容器中。
在这里插入图片描述
运行环境参数VM options 设置为 -Dos.name=linux (— 以linux环境运行),然后运行test01方法,控制台打印结果如下,说明以linux环境启动时,确实只有xiaohong被注册到了IOC容器中。
在这里插入图片描述

3 注意

Conditional相关的注解在真实项目中很有用,这里也给自己提醒一下,在实际开发中心里一定要经常有这根弦,遇到相关问题时,千万不要忘记使用。

发布了189 篇原创文章 · 获赞 187 · 访问量 39万+

猜你喜欢

转载自blog.csdn.net/nrsc272420199/article/details/88738093