@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 Windows() {
- 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 时触发实例化.
来源: https://www.cnblogs.com/haha12/p/11304738.html