• Spring入门(六):条件化的bean


    1. 概念

    默认情况下,Spring中定义的bean在应用程序启动时会全部装配,不管当前运行的是哪个环境(Dev,QA或者Prod),也不管当前运行的是什么系统(Windows或者Linux),但有些使用场景下,我们可能需要条件化的装配某些bean,即当满足某一条件时,装配某些bean,当不满足某一条件时,就忽略掉某些bean。

    这个条件可以很简单,比如当某个jar包存在时,当存在某个环境变量时,也可以很复杂。

    针对这个使用场景,Spring中提供了@Conditional注解来实现条件化的bean。

    2. 示例

    为了更好的理解,我们通过具体的代码示例来理解下条件化的bean的实现方式。

    由于Windows系统和Linux系统显示列表的命令不同,Windows下是dir,Linux下是ls,因此我们的需求是,应用程序启动时自动根据当前系统装配需要的bean,比如我的电脑系统是Windows 7,那就只装配Windows系统所需要的bean。

    首先,定义一个接口ListService,该接口只包含一个方法showListCmd:

    package chapter03.conditional;
    
    public interface ListService {
        String showListCmd();
    }
    

    然后定义该接口的2个实现类WindowsListService和LinuxListService:

    package chapter03.conditional;
    
    public class WindowsListService implements ListService {
        public WindowsListService() {
            System.out.println("This is WindowsListService constructor");
        }
        
        @Override
        public String showListCmd() {
            return "dir";
        }
    }
    
    package chapter03.conditional;
    
    public class LinuxListService implements ListService {
        public LinuxListService() {
            System.out.println("This is LinuxListService constructor");
        }
        
        @Override
        public String showListCmd() {
            return "ls";
        }
    }
    

    然后分别定义Windows系统和Linux系统的判断条件:

    package chapter03.conditional;
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    public class WindowsCondition implements Condition {
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            return conditionContext.getEnvironment().getProperty("os.name").contains("Windows");
        }
    }
    
    package chapter03.conditional;
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    public class LinuxCondition implements Condition {
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            return conditionContext.getEnvironment().getProperty("os.name").contains("Linux");
        }
    }
    

    值得注意的是,这2个类都需要实现Condition接口,并重写方法matches(),如果该方法返回true时,使用该条件的1个或多个bean就会被装配,如果该方法返回false,使用该条件的1个或多个bean就会被忽略。

    然后,定义Java配置类ConditionalConfig:

    package chapter03.conditional;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Conditional;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class ConditionalConfig {
        @Bean
        @Conditional(WindowsCondition.class)
        public ListService windowsListService() {
            return new WindowsListService();
        }
    
        @Bean
        @Conditional(LinuxCondition.class)
        public ListService linuxListService() {
            return new LinuxListService();
        }
    }
    

    这里声明bean时除了使用@Bean注解,还使用了@Conditional注解,这个注解是实现条件化的bean的关键,它的参数可以传递任何实现了Condition接口并重写了matches()方法的类,这里传递的是我们上面定义的WindowsCondition和LinuxCondition。

    最后,我们定义一个Main类,在其main()方法中添加如下测试代码:

    package chapter03.conditional;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class Main {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionalConfig.class);
    
            ListService listService = context.getBean(ListService.class);
    
            System.out.println(context.getEnvironment().getProperty("os.name") + "系统下的列表命令为:" + listService.showListCmd());
    
            context.close();
        }
    }
    

    运行结果如下所示:

    This is WindowsListService constructor

    Windows 7系统下的列表命令为:dir

    从运行日志可以看出,由于当前系统是Windows 7,我们声明的linuxListService bean并没有被装配。

    3. 源码及参考

    源码地址:https://github.com/zwwhnly/spring-action.git,欢迎下载。

    汪云飞《Java EE开发的颠覆者:Spring Boot实战》

    Craig Walls 《Spring实战(第4版)》

    原创不易,如果觉得文章能学到东西的话,欢迎点个赞、评个论、关个注,这是我坚持写作的最大动力。

    如果有兴趣,欢迎添加我的微信:zwwhnly,等你来聊技术、职场、工作等话题(PS:我是一名奋斗在上海的程序员)。

  • 相关阅读:
    《区块链100问》第51集:区块链资产有匿名性
    《区块链100问》第52集:区块链资产能去中心化记账
    《区块链100问》第53集:区块链资产不可复制
    day 5 模块导入、常用模块os shutil sys commands subprocess hashlib json pickle zipfile traceback random datetime pathlib
    apache中配置php支持模块模式、cgi模式和fastcgi模式的实验
    day3--集合、文件操作、字符编码与转换、函数(递归,lambda,filter,map)、字典排序
    练习题目 :if for while else range、xrange、zip
    解决mySQL占用内存超大问题
    my.cnf重要配置参数说明
    chattr与lsattr命令详解
  • 原文地址:https://www.cnblogs.com/zwwhnly/p/11343980.html
Copyright © 2020-2023  润新知