Spring - 关于条件注解的一些理解

前言

@Conditional是Spring4提供的注解,它可以根据条件判断是否将Bean注册到容器中,源码如下:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    Class<? extends Condition>[] value();
}

简单示例

举一个简单的例子,如何根据当前操作系统来进行对象实例化

  • 接口
public interface SystemInter {
    String get();
}
  • 实现类
public class Linux implements SystemInter {
    @Override
    public String get() {
        return "System's Linux";
    }
}

public class Windows implements SystemInter {
    @Override
    public String get() {
        return "System's windows";
    }
}
  • 控制器
public class TestController {
    @Autowired
    private SystemInter systemInter;

    @GetMapping(value = "/system")
    public String getSystem(){
        return systemInter.get();
    }
}

上述代码用于表示操作系统的两个对象,问题来了,如何根据操作系统进行相应的对象实例化,在控制器中注入呢?

这里就可以用到@Conditional注解,通过实现Condition接口重写方法来自定义match规则,Condition接口需要实现matches方法,返回true则注入bean,false则不注入。

  • 条件类
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) {
    	// 获取配置文件中system.condition的属性
        String name = conditionContext.getEnvironment().getProperty("system.condition");
        return "linux".equalsIgnoreCase(name);
    }
}

public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
    	// 获取配置文件中system.condition的属性
        String name = conditionContext.getEnvironment().getProperty("system.condition");
        return "windows".equalsIgnoreCase(name);
    }
}
  • application.properties的配置,配置操作系统为windows
system.condition = windows
  • 创建SystemConfiguration 类,用于配置两个实例的注入
@Configuration
public class SystemConfiguration {

    @Bean
    @Conditional(LinuxCondition.class)
    public SystemInter linux() {
        return new Linux();
    }

    @Bean
    @Conditional(WindowsCondition.class)
    public SystemInter windows() {
        return new Windows();
    }
}
  • 由上述代码可以看出,我们给两个操作系统对象分别建立的对应的条件类,并通过配置文件中的system.condition属性来判断是否实例化。
  • 访问接口结果如下,可以看出,我们从配置文件读取操作系统类型并实例化了windows对象。
    在这里插入图片描述
  • 切换application.properties的操作系统配置为linux
system.condition = linux
  • 访问结果如下:
    在这里插入图片描述
  • 这是个简单的例子,却体现了Spring的策略模式(根据环境或者条件的不同选择不同的算法或者策略来完成该功能)

  • 注:以上的示例将@Conditional标注在方法上,而@Conditional标注在类上可以判断该配置类中的所有Bean是否注入。

内置的条件注解

注解条件
@ConditionalOnBean当SpringIoC容器内存在指定Bean的条件
@ConditionalOnMissingBean当SpringIoC容器内不存在指定Bean的条件
@ConditionalOnClass当SpringIoC容器内存在指定Class的条件
@ConditionalOnMissingClass当SpringIoC容器内不存在指定Class的条件
@ConditionalOnProperty指定的属性是否有指定的值
@ConditionalOnResource类路径是否有指定的值
@ConditionalOnWebApplication当前项目是Web项目的条件
@ConditionalOnNotWebApplication当项目不是Web项目的条件
@ConditionalOnExpression基于SpEL表达式作为判断条件
@ConditionalOnJava基于JVM版本作为判断条件
@ConditionalOnJndi在JNDI存在时查找指定的位置
@ConditionalOnSingleCandidate当指定Bean在SpringIoC容器内只有一个,或者虽然有多个但是指定首选的Bean

- End -
- 个人学习笔记 -
- 仅供参考 -

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Maggieq8324

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值