springboot之@conditional注解

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:
例如:随着对springboot的简单使用后,对springboot源码中的一些注解不太明白,为了之后开启springboot源码读取的困难,做一些预备工作,来开始了解和记录一些遇到的一部分注解吧


提示:以下是本篇文章正文内容,下面案例可供参考

一、@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.condtionContext

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

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

案例

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

1.SystemBean

@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;
       }
   }
  1. 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;
       }
   }

3.测试类

	/**
	 * @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,因为我这边是windows电脑,所以实例化的是windows的SystemBean
  2. 需要注意一点:我们可以看出mac并不为null,而是window实例化的bean,不管你命名什么,都可以注入这个bean

修改一下配置

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

    // @Conditonal({WindowsConfig.class})

通过运行结果可以看出,配置类的两个bean都已经注册成功。
注意:当同一个对象被注入两次及以上的时候,那么你在使用当前对象的时候,名称一定是要两个bean名称的一个,否则报错。比如修改为:

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

在启动时,报错了


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了@condition注解的使用和含义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值