From 9dd99636b932efdf312ac203c20ce4cd917f3b00 Mon Sep 17 00:00:00 2001 From: xuchengsheng Date: Thu, 12 Oct 2023 22:41:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96@Conditional?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring-annotation-conditional/README.md | 64 ++++++++++--------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/spring-annotation/spring-annotation-conditional/README.md b/spring-annotation/spring-annotation-conditional/README.md index 89b1355..eaa9c6b 100644 --- a/spring-annotation/spring-annotation-conditional/README.md +++ b/spring-annotation/spring-annotation-conditional/README.md @@ -1,25 +1,31 @@ ## @Conditional - [@Conditional](#conditional) - - [一、注解描述](#一注解描述) - - [二、注解源码](#二注解源码) - - [三、主要功能](#三主要功能) - - [四、最佳实践](#四最佳实践) - - [4.1、在@Bean上使用](#41在bean上使用) - - [4.2、在@Configuration上使用](#42在configuration上使用) - - [4.3、自定义组合注解](#43自定义组合注解) - - [五、时序图](#五时序图) - - [六、源码分析](#六源码分析) - - [七、注意事项](#七注意事项) - - [八、总结](#八总结) - - [8.1、最佳实践总结](#81最佳实践总结) - - [8.2、源码分析总结](#82源码分析总结) + - [一、基本信息](#一基本信息) + - [二、注解描述](#二注解描述) + - [三、注解源码](#三注解源码) + - [四、主要功能](#四主要功能) + - [五、最佳实践](#五最佳实践) + - [在@Bean上使用](#在bean上使用) + - [在@Configuration上使用](#在configuration上使用) + - [自定义组合注解](#自定义组合注解) + - [六、时序图](#六时序图) + - [七、源码分析](#七源码分析) + - [八、注意事项](#八注意事项) + - [九、总结](#九总结) + - [最佳实践总结](#最佳实践总结) + - [源码分析总结](#源码分析总结) -### 一、注解描述 + +### 一、基本信息 + +✒️ **作者** - Lex 📝 **博客** - [我的CSDN](https://blog.csdn.net/duzhuang2399/article/details/133800722) 📚 **文章目录** - [所有文章](https://github.com/xuchengsheng/spring-reading) 🔗 **源码地址** - [@Conditional源码](https://github.com/xuchengsheng/spring-reading/tree/master/spring-annotation/spring-annotation-conditional) + +### 二、注解描述 `@Conditional`注解,是用来基于满足某些特定条件来决定一个Bean是否应该被注册到Spring容器的。这提供了一种灵活的方式来根据环境、配置或其他因素来决定是否激活或者创建某个Bean。 -### 二、注解源码 +### 三、注解源码 `@Conditional`注解是 Spring 框架自 3.0 版本开始引入的一个核心注解,用于指示一个组件只在所有指定条件匹配时才能被注册。 @@ -60,7 +66,7 @@ public @interface Conditional { } ``` -### 三、主要功能 +### 四、主要功能 1. **条件化 Bean 注册** + 可以根据特定的条件来决定是否创建并注册一个 Bean。这允许我们根据环境、配置或其他因素动态地选择哪些 Bean 需要被实例化。 @@ -75,9 +81,9 @@ public @interface Conditional { 6. **不支持继承** + `@Conditional` 注解本身不是继承的,因此,从父类或接口继承的条件不会被子类考虑。 -### 四、最佳实践 +### 五、最佳实践 -#### 4.1、在@Bean上使用 +#### 在@Bean上使用 首先来看看启动类入口,首先设置一个系统属性`enable.bean`为`true`,然后上下文环境使用`AnnotationConfigApplicationContext`(此类是使用Java注解来配置Spring容器的方式),构造参数我们给定了一个`MyConfiguration`组件类,最后打印了Spring上下文中所有的bean定义名称。 @@ -151,7 +157,7 @@ beanDefinitionName = myBeanConfiguration beanDefinitionName = user2 ``` -#### 4.2、在@Configuration上使用 +#### 在@Configuration上使用 首先来看看启动类入口,首先设置一个系统属性`enable.config`为`true`,然后上下文环境使用`AnnotationConfigApplicationContext`(此类是使用Java注解来配置Spring容器的方式),构造参数我们给定了一个`MyConfiguration`组件类,最后打印了Spring上下文中所有的bean定义名称。 @@ -224,7 +230,7 @@ beanDefinitionName = user4 无任何bean ``` -#### 4.3、自定义组合注解 +#### 自定义组合注解 首先来看看启动类入口,首先设置一个系统属性`enable.custom`为`true`,然后上下文环境使用`AnnotationConfigApplicationContext`(此类是使用Java注解来配置Spring容器的方式),构造参数我们给定了一个`MyConfiguration`组件类,最后打印了Spring上下文中所有的bean定义名称。 @@ -308,7 +314,7 @@ beanDefinitionName = user6 无任何bean ``` -### 五、时序图 +### 六、时序图 ~~~mermaid sequenceDiagram @@ -330,7 +336,7 @@ ConditionEvaluator->>AnnotatedBeanDefinitionReader:返回true or false AnnotatedBeanDefinitionReader->>AnnotatedBeanDefinitionReader:如果shouldSkip返回是true,跳过Bean的注册 ~~~ -### 六、源码分析 +### 七、源码分析 首先来看看启动类入口,首先设置一个系统属性`enable.custom`为`true`,然后上下文环境使用`AnnotationConfigApplicationContext`(此类是使用Java注解来配置Spring容器的方式),构造参数我们给定了一个`MyConfiguration`组件类,最后打印了Spring上下文中所有的bean定义名称。 @@ -511,7 +517,7 @@ private Condition getCondition(String conditionClassName, @Nullable ClassLoader } ``` -### 七、注意事项 +### 八、注意事项 1. **实现 `Condition` 接口** + 为了使用 `@Conditional`, 我们需要实现 `Condition` 接口。该接口只有一个方法,`matches(ConditionContext context, AnnotatedTypeMetadata metadata)`,我们需要在这里放置我们的条件逻辑。 @@ -533,9 +539,9 @@ private Condition getCondition(String conditionClassName, @Nullable ClassLoader 9. **注意与 `@Profile` 的区别** + 虽然 `@Conditional` 和 `@Profile` 在某些情况下可以达到相同的效果,但它们的目的不同。`@Profile` 基于环境,而 `@Conditional` 更加通用,允许我们基于任意条件创建 bean。 -### 八、总结 +### 九、总结 -#### 8.1、最佳实践总结 +#### 最佳实践总结 1. **基于`@Bean`的条件配置** @@ -545,7 +551,7 @@ private Condition getCondition(String conditionClassName, @Nullable ClassLoader - **结果**: - 当条件满足(如`enable.bean`为`true`),特定的bean(如`user1`)会被注册。 - - 当条件不满足,该bean不会被注册。 + - 当条件不满足,该bean不会被注册。 2. **基于`@Configuration`的条件配置** @@ -555,7 +561,7 @@ private Condition getCondition(String conditionClassName, @Nullable ClassLoader - **结果**: - 当条件满足(如`enable.config`为`true`),配置类被激活,其内部的所有beans(如`user3`和`user4`)都会被注册。 - - 当条件不满足,配置类及其内部定义的所有beans都不会被注册。 + - 当条件不满足,配置类及其内部定义的所有beans都不会被注册。 3. **使用自定义组合注解** @@ -565,9 +571,9 @@ private Condition getCondition(String conditionClassName, @Nullable ClassLoader - **结果**: - 当条件满足(如`enable.custom`为`true`),带有`@ConditionalOnCustomActive`注解的配置类或bean会被注册。 - - 当条件不满足,它们不会被注册。 + - 当条件不满足,它们不会被注册。 -#### 8.2、源码分析总结 +#### 源码分析总结 1. **初始化与启动** - 通过 `AnnotationConfigApplicationContext` 构造函数初始化 Spring 上下文,并通过 `register` 和 `refresh` 方法完成 bean 的注册和容器的刷新。