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:我是一名奋斗在上海的程序员)。

Spring入门(六):条件化的bean的更多相关文章

  1. (二)spring 高级装配-Condition -条件化的bean

    Condition:满足某个特定条件的情况下创建bean 条件化配置bean: a:@Conditional 指定一个class ,它指明了通过条件对比的类.如果没有指定class则通过Condito ...

  2. Spring 梳理-profile与条件化定义bean

    定义profile <beans> //root <beans profile="dev"> <bean id=.../> </beans ...

  3. 第3章—高级装配—条件化的Bean

    条件化的Bean 通过活动的profile,我们可以获得不同的Bean.Spring 4提供了一个更通用的基于条件的Bean的创建方式,即使用@Conditional注解. @Conditional根 ...

  4. 【Java Web开发学习】Spring4条件化的bean

    [Java Web开发学习]Spring4条件化的bean 转载:https://www.cnblogs.com/yangchongxing/p/9071960.html Spring4引入了@Con ...

  5. Spring入门(4)-注入Bean属性

    Spring入门(4)-注入Bean属性 本文介绍如何注入Bean属性,包括简单属性.引用.内部Bean.注入集合等. 0. 目录 注入简单值 注入引用 注入内部Bean 装配集合 装配空值 使用命名 ...

  6. 002Conditional条件化创建bean

    01.条件化配置bean @Bean @Conditional(MagicExistsCondition.class)---->条件化创建bean public MagicBean magicB ...

  7. Spring入门2. IoC中装配Bean

    Spring入门2. IoC中装配Bean 20131125 前言: 上一节学习了Spring在JavaProject中的配置,通过配置文件利用BeanFactory和ApplicationConte ...

  8. Spring高级装配(二) 条件化的bean

    如果你希望一个bean在特定的条件下才会出现: 应用的类路径下包含特定的库时才创建 只有当某个特定的bean也声明之后才会创建 某个特定的环境变量设定之后才创建某个bean 在Spring 4之前,很 ...

  9. Spring入门(二):自动化装配bean

    Spring从两个角度来实现自动化装配: 组件扫描(component scanning):Spring会自动发现应用上下文中需要创建的bean. 自动装配(autowiring):Spring会自动 ...

随机推荐

  1. 解决thinkphp在开发环境下文件模块找不到的问题

    win10系统下,phpstudy开发环境下小问题描述: 找不到public公共模块. Not Found The requested URL /public/admin/login.html was ...

  2. Python入门基础(2)

    如果你是博客园团队,,看到不符合您们要求的地方可否指出来?不要你不符合要求,然后我不符合哪项要求?是要我自己去找么? python条件语句 首先介绍的是if语句,python中的if语句格式如下: i ...

  3. C++学习书籍推荐《More Effective C++》下载

    百度云及其他网盘下载地址:点我 编辑推荐 <More Effective C++:35个改善编程与设计的有效方法(中文版)>:传世经典书丛 媒体推荐 <Effective c++&g ...

  4. 预学第三天:Ge常用t快捷键,码云,Git使用

    目录 Get常用快捷键 码云及Git的使用 Get常用快捷键 git init #创建一个本地的仓库 **gie add test.txt #指定文件添加 ***git add . #当前文件夹下所有 ...

  5. 通过windug判断某个模块导致程序不能退出。

    1.windug附加进程. 2.~* kb 3.看堆栈

  6. UVA101 The Blocks Problem 题解

    题目链接:https://www.luogu.org/problemnew/show/UVA101 这题码量稍有点大... 分析: 这道题模拟即可.因为考虑到所有的操作vector可最快捷的实现,所以 ...

  7. 成为高级 React 开发你需要知道的知识点

    简评:除了常见的 HOC 和 RenderProp 技巧,作者介绍了 7 个有用的知识点. 使用 Fragment 而不是 div 很多时候我们想要处理多个 component,但是 render 只 ...

  8. AppBoxFuture: 二级索引及索引扫描查询数据

      数据库索引对于数据查询的重要性不可言喻,因此作者在存储层实现了二级索引,以及利用索引进行扫描的功能.目前仅实现了分区表与非分区表的本地索引(数据与索引共用一个Raft组管理),全局索引及反向索引待 ...

  9. python购物车升级版

    各文件内容 前言 功能架构等请参考前一篇博客,此篇博客为进阶版的存代码展示. 详细文件内容 启动文件 starts.py启动文件 import os import sys BASE_DIR = os. ...

  10. <<Modern CMake>> 翻译 2. CMake 基础

    <<Modern CMake>> 翻译 2. CMake 基础 最低版本 这是每个 CMakeLists.txt 文件的第一行.CMakeLists.txt 是 CMake 所 ...