SpringBoot @Conditional的使用

结构说明
在这里插入图片描述

hello-spring-boot-starter: 没什么用,引用了autoconfigure模块
hello-spring-boot-starter-autoconfigure: 主要的自定义的starter模块
hello-spring-boot-web-demo: web模块
详情可以看:入门SpringBoot自定义starter

1、@Conditional注解的说明

@Conditional是Spring4.0出现的新特性,他可以选择性的创建Bean。

判断是否满足当前条件,如果满足则创建Bean,不满足则不创建

2、思路

根据说明可以了解到,@Conditional的作用是判断是否满足当前条件,如果满足则创建Bean,不满足则不创建

我们的思路是看看web模块是否能够注入starter提供的Bean
1、如果条件满足则成功创建,通过接口能成功拿到返回值
2、如果条件满足则成功创建,通过接口不能拿到返回值

2、autoconfigure模块

根据上次的自定义starter直接创建一个Bean

3、@Conditional的使用

3.1、SpringBoot是如何实现这个功能的

这是DispatcherServlet的自动注册配置类:
@Conditional接口是说如果DispatcherServletRegistrationCondition满足条件才会去配置
在这里插入图片描述

看下它的继承关系图:
顶层也是一个Condition的接口,然后SpringBoot自己去封装了Condition的模块方法。
你不信可以去看看其他的,比如Redis的相关配置,也会发现都是继承SpringBootCondition。
在这里插入图片描述

所以我们可以得出结论:
1、实现Condition接口并重写matches方法
2、继承SpringBootCondition抽象类并重写getMatchOutcome方法

3.2、造轮子

跟着SpringBoot的思路,我们去实现第一种:实现Condition接口并重写matches方法。
如果返回值为true则@Conditional则认为符合条件

Condition的编写

public class WindowCondition implements Condition {
    
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // todo 拿配置文件的信息
        return true;
    }
}

Service的编写

public interface CmdService {

    String print(String cmd);
}
public class WindowCmdService implements CmdService {
    @Override
    public String print(String cmd) {
        return "window cmd ...";
    }
}

自动配置类

public class CmdServiceConditionAutoConfiguration {

    /**
     * 当WindowCondition方法中的matches返回true的时候,
     * WindowCmdService会被注入,否则不注入。
     */
    @Bean
    @Conditional(WindowCondition.class)
    public WindowCmdService windowComService(){
        return new WindowCmdService();
    }
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.mecuros.springboot.custom.starter.CmdServiceConditionAutoConfiguration

4、验证

在web模块引入starter并写出Controller接口

@RestController("/conditional")
public class ConditionalController {

    @Resource
    private WindowCmdService windowCmdService;

    @GetMapping("/window/{cmd}")
    public String window(@PathVariable String cmd){
        return windowCmdService.print(cmd);
    }
}

4.1、不用@Conditional的情况

不用@Conditional注解默认会创建WindowService
image.png

4.2、用@Conditional的情况

4.2.1、WindowConditional为true时

一切正常
image.png

4.2.2、WindowConditional为false时

image.png
image.png

5、总结

我们发现:
当Conditional为false,SpringBoot会报错。
当Conditional为true,接口正常。


证明:@Conditional注解需要配合两种方法使用
1、实现Condition接口并重写matches方法
2、继承SpringBootCondition抽象类并重写getMatchOutcome方法
并且在自动配置那里配合@Bean来一起使用。

6、其他知识点(待验证,后面会继续验证)

@Conditional扩展注解 作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean;
@ConditionalOnMissingBean 容器中不存在指定Bean;
@ConditionalOnExpression 满足SpEL表达式指定
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值