A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

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;@Configurationpublic 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,欢迎下载。

2 个回复

倒序浏览
有任何问题欢迎在评论区留言
回复 使用道具 举报
或者添加学姐微信
DKA-2018
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马