助力SpringBoot自动配置的条件注解ConditionalOnXXX分析--SpringBoot源码(三)
2020/3/1 17:14:43
本文主要是介绍助力SpringBoot自动配置的条件注解ConditionalOnXXX分析--SpringBoot源码(三),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
注:该源码分析对应SpringBoot版本为2.1.0.RELEASE
1 前言
本篇接 如何分析SpringBoot源码模块及结构?--SpringBoot源码(二)
上一篇分析了SpringBoot源码结构及各个模块pom之间的关系后,那么此篇开始就开始解开SpringBoot新特性之一--自动配置的神秘面纱了。因为SpringBoot自动配置原理是基于其大量的条件注解ConditionalOnXXX
,因此,本节我们先来撸下Spring的条件注解的相关源码。
2 SpringBoot的派生条件注解
我们都知道,SpringBoot自动配置是需要满足相应的条件才会自动配置,因此SpringBoot的自动配置大量应用了条件注解ConditionalOnXXX
。如下图:
那么上图的条件注解如何使用呢?
举个栗子,我们来看下如何使用
@ConditionalOnClass
和@ConditionalOnProperty
这两个注解,先看下图代码:HelloWorldEnableAutoConfiguration
这个自动配置类应用了@ConditionalOnClass
和ConditionalOnProperty
两个条件注解,那么只有在满足:classpath
中存在HelloWorldComponent.class
和配置了hello.world.name
和hello.world.age
属性这两个条件的情况下才会创建HelloWorldComponent
这个bean
。
其实SpringBoot的@ConditionalOnXXX
等条件注解都是派生注解,那么什么是派生注解呢?
就拿上面的栗子来说,以@ConditionalOnClass(HelloWorldComponent.class)
为例,我们打开ConditionalOnClass
注解源码,如下:
@Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnClassCondition.class) public @interface ConditionalOnClass { Class<?>[] value() default {}; String[] name() default {}; } 复制代码
可以看到@ConditionalOnClass
注解上面又标注了@Conditional(OnClassCondition.class)
注解,因此@ConditionalOnClass
是@Conditional
的派生注解,@Conditional(OnClassCondition.class)
和@ConditionalOnClass
注解是等价的,即这两个注解标注在某个配置类上的效果是等价的。
而SpringBoot的自动配置原理正是建立在这些大量的派生条件注解@ConditionalOnXXX
之上,而这些条件注解的原理跟Spring的Condition接口有关。因此我们先来研究下Condition接口的相关源码。
3 Condition接口
3.1 Condition接口源码分析
分析Condition接口源码前先看下如何自定义ConditionalOnXXX
注解,举个栗子,比如自定义一个@ConditionalOnLinux
注解,该注解只有在其属性environment
是"linux"才会创建相关的bean。定义了以下代码:
/** * 实现spring 的Condition接口,并且重写matches()方法,如果@ConditionalOnLinux的注解属性environment是linux就返回true * */ public class LinuxCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // 获得注解@ConditionalOnLinux的所有属性 List<AnnotationAttributes> allAnnotationAttributes = annotationAttributesFromMultiValueMap( metadata.getAllAnnotationAttributes( ConditionalOnLinux.class.getName())); for (AnnotationAttributes annotationAttributes : allAnnotationAttributes) { // 获得注解@ConditionalOnLinux的environment属性 String environment = annotationAttributes.getString("environment"); // 若environment等于linux,则返回true if ("linux".equals(environment)) { return true; } } return false; } } 复制代码
@Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(LinuxCondition.class) public @interface ConditionalOnLinux { // 标注是哪个环境 String environment() default ""; } 复制代码
@Configuration public class ConditionConfig { // 只有`@ConditionalOnLinux`的注解属性`environment`是"linux"时才会创建bean @Bean @ConditionalOnLinux(environment = "linux") public Environment linuxEnvironment() { return new
这篇关于助力SpringBoot自动配置的条件注解ConditionalOnXXX分析--SpringBoot源码(三)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-27JavaScript面试真题详解与解答
- 2024-12-27掌握JavaScript大厂面试真题:新手入门指南
- 2024-12-27JavaScript 大厂面试真题详解与解析
- 2024-12-26网络攻防资料入门教程
- 2024-12-26SQL注入资料详解:入门必读教程
- 2024-12-26初学者指南:数据库服务漏洞项目实战
- 2024-12-26网络安全项目实战:新手入门指南
- 2024-12-26网络攻防项目实战入门教程
- 2024-12-26信息安全项目实战:从入门到初步应用
- 2024-12-26SQL注入项目实战:初学者指南