• Spring条件注解@Conditional


    @Conditional是Spring4新提供的注解,它的作用是根据某个条件创建特定的Bean,通过实现Condition接口,并重写matches接口来构造判断条件。总的来说,就是根据特定条件来控制Bean的创建行为,这样我们可以利用这个特性进行一些自动的配置。

      本文将分为三大部分,@Conditional源码的介绍、Condition的使用示例和@Conditional的扩展注解的介绍。

    一、@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注解可以用在类和方法上,需要传入一个实现了Condition接口class数组。

    二、代码示例

    下面将以不同的操作系统为条件,通过实现Condition接口,并重写其matches方法来构造判断条件。若在Windows系统下运行程序,则输出列表命令为dir;若在Linux系统下运行程序,则输出列表命令为ls。

    1.判断条件类的定义

    (1).判断Windows的条件
    package com.study.day01;
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    /**
     * @Auther: lifq
     * @Description:
     */
    public class WindowsCondition implements Condition {
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            return context.getEnvironment().getProperty("os.name").contains("Windows");
        }
    }

     (2).判断Linux的条件

    package com.study.day01;
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    /**
     * @Auther: lifq
     * @Description:
     */
    public class LinuxCondition implements Condition {
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            return context.getEnvironment().getProperty("os.name").contains("Linux");
        }
    }

    2.不同系统下的Bean的类

    (1).接口代码
    package com.study.day01;
    
    import org.springframework.stereotype.Service;
    
    /**
     * @Auther: lifq
     * @Description:
     */
    public interface ListService {
    
        public String showListCmd();
    
    }

      (2).Windows实现类代码

    package com.study.day01;
    
    /**
     * @Auther: lifq
     * @Description:
     */
    public class WindowsService implements ListService {
        public String showListCmd() {
            return "dir";
        }
    }

     (3).Linux实现类代码

    package com.study.day01;
    
    /**
     * @Auther: lifq
     * @Description:
     */
    public class LinuxService implements ListService {
        public String showListCmd() {
            return "ls";
        }
    }

      3.配置类

    package com.study.day01;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Conditional;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @Auther: lifq
     * @Description:
     */
    @Configuration
    public class Config {
    
        @Bean
        @Conditional(WindowsCondition.class)
        public ListService window() {
            return new WindowsService();
        }
    
        @Bean
        @Conditional(LinuxCondition.class)
        public ListService linux() {
            return new LinuxService();
        }
    }

      4.运行类

    package com.study.day01;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    /**
     * @Auther: lifq
     * @Description:
     */
    public class Main01 {
    
        public static void main (String []args) {
    
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
    
            ListService listService = applicationContext.getBean(ListService.class);
    
            System.out.println(applicationContext.getEnvironment().getProperty("os.name") + "系统下的列表命令为:" + listService.showListCmd());
        }
    }

     我的是Windows操作系统,输出结果为dir,运行截图如下:

    运行截图

    @Conditional注解例子演示完成,有问题欢迎留言沟通哦!

    完整源码地址:https://github.com/suisui2019/springboot-study

    三、@Conditional的扩展注解

    @ConditionalOnBean:仅仅在当前上下文中存在某个对象时,才会实例化一个Bean。
    @ConditionalOnClass:某个class位于类路径上,才会实例化一个Bean。
    @ConditionalOnExpression:当表达式为true的时候,才会实例化一个Bean。
    @ConditionalOnMissingBean:仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean。
    @ConditionalOnMissingClass:某个class类路径上不存在的时候,才会实例化一个Bean。
    @ConditionalOnNotWebApplication:不是web应用,才会实例化一个Bean。
    @ConditionalOnBean:当容器中有指定Bean的条件下进行实例化。
    @ConditionalOnMissingBean:当容器里没有指定Bean的条件下进行实例化。
    @ConditionalOnClass:当classpath类路径下有指定类的条件下进行实例化。
    @ConditionalOnMissingClass:当类路径下没有指定类的条件下进行实例化。
    @ConditionalOnWebApplication:当项目是一个Web项目时进行实例化。
    @ConditionalOnNotWebApplication:当项目不是一个Web项目时进行实例化。
    @ConditionalOnProperty:当指定的属性有指定的值时进行实例化。
    @ConditionalOnExpression:基于SpEL表达式的条件判断。
    @ConditionalOnJava:当JVM版本为指定的版本范围时触发实例化。
    @ConditionalOnResource:当类路径下有指定的资源时触发实例化。
    @ConditionalOnJndi:在JNDI存在的条件下触发实例化。
    @ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者有多个但是指定了首选的Bean时触发实例化。

    推荐阅读

    1.Spring Boot入门-快速搭建web项目
    2.Spring Boot 2.X 整合Redis
    3.Spring Boot 2.X 如何优雅的解决跨域问题?
    4.Spring Boot 2.X 如何添加拦截器?
    5.Spring Boot 2.X 集成spring session实现session共享
    6.Redis Cluster搭建高可用Redis服务器集群
    7.为什么单线程的Redis这么快?
    8.一篇文章搞定SpringMVC参数绑定
    9.SpringMVC+Mybatis 如何配置多个数据源并切换?


    限时领取免费Java相关资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo/Kafka、Hadoop、Hbase、Flink等高并发分布式、大数据、机器学习等技术。

    资料传送门:  https://mp.weixin.qq.com/s/u2b_NVNuMuAPE0w4lc45fw

    关注下方公众号即可免费领取:

    Java碎碎念公众号

  • 相关阅读:
    SQL ——索引、视图和事务
    流控制语句
    SQL Server 高级编程之T-SQL 编程函数
    SQL高级编程之waitfor
    数据库主键、外键、唯一等约束
    打代码会遇到的单词
    前端词云图
    docker+mysql集群+读写分离+mycat管理+垂直分库+负载均衡
    lvs+keepalived实现Mycat的负载均衡--高可用
    mycat配置数据库集群
  • 原文地址:https://www.cnblogs.com/haha12/p/11304738.html
Copyright © 2020-2023  润新知