因为不知道条件注解@Conditional,错失15K的Offer!

01 引言

前两天刷到大V程序员鱼皮视频面试现场,在直播面试的时候问到:怎么保证开发的SDK的时候,部分Bean 的实例化根据配置项实例化,没有配置就不实例化?

候选人支支吾吾半天,说到拦截器、过滤器等,就是没有条件注解,硬是逼着鱼皮自己说了。自然也就失去了这份Offer。

其实这个条件注解就是@Conditional ,它是 Spring4.0版本框架的一个核心注解,专门用于 根据条件动态注册 Bean。我们今天来了解一下这个注解。

02 案例

假设我们需要按照不同的环境初始化不同的Bean,Windows下创建Windows相关的Bean,Linux下创建Linux相关的Bean

2.1 Bean定义

Windows下的Bean

java 复制代码
public class WindowBean {

    public WindowBean() {
        System.out.println("WindowBean 构造器执行完成");
    }
}

Linux 下的Bean

java 复制代码
public class LinuxBean {

    public LinuxBean() {
        System.out.println("LinuxBean 构造器执行完成");
    }
}

2.2 配置

java 复制代码
@Configuration
public class BeanConfig {

    @Bean
    public WindowBean windowBean() {
        return new WindowBean();
    }

    @Bean
    public LinuxBean linuxBean() {
        return new LinuxBean();
    }
}

2.3 启动测试

目前我们没有做任何的关于条件注解的配置,项目启动之后会这两个Bean都会被实例化。如图:

2.4 编写条件

根据环境变量os.name匹配。

java 复制代码
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String osName = context.getEnvironment().getProperty("os.name");
        System.out.println("WindowsCondition osName: " + osName);
        return "win".equals(osName);
    }
}

public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String osName = context.getEnvironment().getProperty("os.name");
        System.out.println("LinuxCondition osName: " + osName);
        return "linux".equals(osName);
    }
}

2.5 修改配置

WindowBean在匹配WindowsCondition 逻辑的时候,实例化BeanLinuxBean 在匹配LinuxCondition 逻辑的时候,才会实例化。

java 复制代码
@Configuration
public class BeanConfig {

    @Bean
    @Conditional(WindowsCondition.class)
    public WindowBean windowBean() {
        return new WindowBean();
    }

    @Bean
    @Conditional(LinuxCondition.class)
    public LinuxBean linuxBean() {
        return new LinuxBean();
    }
}

启动命令上,增加os.name=win的配置:

2.6 验证

03 源码追踪

因为使用的是注解,我们就直接看注解的上下文,以此为入口:

org.springframework.context.annotation.AnnotationConfigApplicationContext

关键代码块:

可以看到,在shouldSkip()方法中,首先会判断类或方法上是否标注了@Conditional注解,如果没有标注@Conditional注解,则直接返回false。

此时,调用的doRegisterBean()方法根据shouldSkip()的返回,决定要不要把对应的Bean会被创建并注入到IOC容器中。

自此,条件注解的内幕也就被了。

04 扩展

其实我们在平时使用的时候,往往不会直接去用@Conditional注解,反而经常会使用其扩展的注解,如下:


关注我的公众号获取首发内容:【编程朝花夕拾】

相关推荐
Moonbit32 分钟前
MoonBit高校行 | 中大、深技大、深大、港科广回顾
后端·开源·编程语言
银帅1833503097134 分钟前
2018年下半年试题四:论NoSQL数据库技术及其应用
数据库·架构·nosql
纸照片36 分钟前
【邪修玩法】如何在WPF中开放 RESTful API 服务
后端·wpf·restful
心态特好1 小时前
详解WebSocket及其妙用
java·python·websocket·网络协议
文火冰糖的硅基工坊1 小时前
《投资-107》价值投资者的认知升级与交易规则重构 - 上市公司的估值,估的不是当前的净资产的价值,而是未来持续赚钱的能力,估的是公司未来所有赚到钱的价值。
重构·架构·投资·投机
文火冰糖的硅基工坊1 小时前
《投资-99》价值投资者的认知升级与交易规则重构 - 什么是周期性股票?有哪些周期性股票?不同周期性股票的周期多少?周期性股票的买入和卖出的特点?
大数据·人工智能·重构·架构·投资·投机
一水鉴天1 小时前
整体设计 逻辑系统程序 之18 Source 容器(Docker)承载 C/P/D 三式的完整设计与双闭环验证 之2
docker·架构·认知科学·公共逻辑
芒果茶叶2 小时前
并行SSR,SSR并行加载
前端·javascript·架构
Haooog2 小时前
98.验证二叉搜索树(二叉树算法题)
java·数据结构·算法·leetcode·二叉树
武子康2 小时前
Java-143 深入浅出 MongoDB NoSQL:MongoDB、Redis、HBase、Neo4j应用场景与对比
java·数据库·redis·mongodb·性能优化·nosql·hbase