Java @ConditionalOnProperty 与 @Conditional

文章记录起因:有个项目中开始时用了对象存储,开始是公司一个同事写的,后来过了一段时间后,甲方要求对象存储换为了华为云存储,问题一是不确定原来的还用不用,问题二是改动的地方有点多,如果一个一个地方的去改,需要换回去的时候又要从头到尾再去改一遍。所以需要实现扩展了华为云存储的服务,同时要简单的能换回原来的服务。
实现逻辑:

  1. 创建一个对象存储的基本接口( IStorageService )
  2. 让原来的服务与现在需要服务都实现这个基本接口( IStorageService )
  3. 各自实现对象存储的逻辑
  4. 两个服务类上使用 @ConditionalOnProperty 注解标明区别
  5. 配置文件配置需要生效的服务

一、@ConditionalOnProperty

@ConditionalOnProperty 是 Spring 框架中的一个条件注解,它允许你根据应用程序的配置属性来控制是否应该创建一个 bean 或配置一个类。
以下是 @ConditionalOnProperty 注解的主要属性及其详细说明:
在这里插入图片描述

  • name:要检查的属性的名称。这是一个必需的属性。

  • havingValue:要求属性必须具有的值。如果未指定,那么属性只要存在就足够。

  • prefix:属性名称的前缀。如果指定了 prefixname 属性值将会被拼接到 prefix 后面。

  • valuename 属性的别名。通常与 name 一起使用,用于提供一个额外的属性名称。

  • matchIfMissing:当属性不存在时,默认值为 false。如果设置为 true,则即使属性不存在,也会视为匹配成功。
    这些属性允许你根据应用程序的配置属性来灵活地控制 bean 或配置类的创建和激活。你可以使用这些属性来根据不同的配置设置,动态地配置和管理应用程序的行为

@ConditionalOnProperty 使用:

@Service
@ConditionalOnProperty(name = "storage.type", havingValue = "huawei")
public class HuaWeiStorImpl implements IStorageService {
@Service
@ConditionalOnProperty(name = "storage.type", havingValue = "qingyun")
public class QjepQingStorServiceImpl implements IStorageService {
@Autowired
private IStorageService storageService;

在上面的示例中,IStorageService 有两个实现类,两个实现类中使用 @ConditionalOnProperty 注解指定了 storage.type 属性,在配置文件中配置 storage.type 这个属性的值来确定生效的服务。当配置文件中的 storage.type 属性值为 huawei 时上面例子中 @Autowired 注入的服务即为 HuaWeiStorImpl 这个服务。

至此这个需求就完成了,下面就是扩展方面了。

二、@Conditional
我们还是来看 @ConditionalOnProperty
在这里插入图片描述
@ConditionalOnProperty 注解类中使用了 @Conditional 注解。我们现在来说一说这个注解。
在这里插入图片描述

@Conditional 是一个元注解,它可以用于创建自定义条件注解,你可以为自定义的条件注解提供条件评估逻辑。以根据特定条件来决定是否应该创建一个特定的 bean 或配置类。

  • value:指定条件评估逻辑的类 。

@Conditional 注释可以以以下任何一种方式使用:如果 @Configuration 类被标记为 @Conditional ,那么与该类相关的所有 @Bean 方法、@Import 注释和 @ComponentScan 注释都将受到这些条件的约束。注意: @Conditional 注释不支持继承;任何来自超类或重写方法的条件都不会被考虑。@Conditional 本身没有声明为 @Inherited ;此外,任何使用 @Conditional 元注释的自定义组合注释都不能声明为 @Inherited

理解了 @Conditional 这个注解后,我们再来看 @ConditionalOnProperty@Conditional 标注的信息为 OnPropertyCondition.class ,所以 OnPropertyCondition 这个类就是为 @ConditionalOnProperty 这个注解供条件评估逻辑的类。
在这里插入图片描述
从源码中我们可以看到 OnPropertyCondition 这个类继承了 SpringBootCondition 接口。我们再继续进去看
在这里插入图片描述SpringBootCondition 是 Spring 框架中的一个内置条件类,Spring Boot 使用的所有 Condition 实现的基础。提供合理的日志记录,帮助用户诊断加载了哪些类。它是一个抽象类,可以理解为这个类对我们需要实现的 Condition 接口做了封装,以便于实现 Condition 接口。
SpringBootCondition 中有一个抽象方法:

  • getMatchOutcome (ConditionContext context, AnnotatedTypeMetadata metadata):根据条件的评估结果返回 ConditionOutcome 对象,表示条件匹配或不匹配的结果。

在继承 SpringBootCondition 类时重写这个方法实现条件评估逻辑。

从源码中我们可以看到 SpringBootCondition 这个类实现了 Condition 接口。
我们再看看 Condition 这个接口干啥的:
在这里插入图片描述
Condition 接口是 Spring 框架中用于定义条件评估逻辑的接口,该接口定义了一个方法 matches,用于评估特定条件是否匹配。通过实现该接口,你可以根据自定义的条件来动态地控制 bean 的创建和激活,从而使得 Spring 应用程序可以更加灵活地适应不同的环境和需求。

  • matches 方法:该方法用于评估特定条件是否匹配。在这个方法中,你可以编写自定义的条件评估逻辑。方法接收两个参数:

  • ConditionContext:当前条件评估的上下文对象,提供了对环境、资源加载器、类加载器等的访问。

  • AnnotatedTypeMetadata:注解元数据对象,提供了对类、方法或字段上的注解信息的访问。

实现了 Condition 接口的类可以根据需要访问 ConditionContextAnnotatedTypeMetadata,并根据具体的条件判断逻辑来决定条件是否匹配。如果条件匹配,则返回 true,否则返回 false

看到这里对于 @ConditionalOnProperty 注解的实现过程有了个清晰的认知了:

  1. 根据需求自定义一个条件注解
  2. 使用 @Conditional 注解为自定义的注解标准自定义条件评估逻辑类
  3. 自定义条件评估逻辑类实现 Condition 接口编写自定义的条件评估逻辑;或者继承 SpringBootCondition 类时重写 getMatchOutcome 方法实现条件评估逻辑。

看到这我们在简单了解下 ConditionContextAnnotatedTypeMetadata ,这两个来是在 Spring 框架中用于条件评估时的两个重要接口,它们提供了访问环境和注解元数据的能力,以便在条件评估过程中做出相应的决策。

ConditionContext

ConditionContext 接口提供了对当前条件评估上下文的访问,包括访问环境、资源加载器、类加载器等。通过 ConditionContext,你可以获得有关当前应用程序上下文和环境的信息,以便在条件评估逻辑中做出相应的判断。

一些常用的方法包括:

  • getBeanFactory ():获取与当前应用程序上下文关联的 Bean 工厂。

  • getEnvironment ():获取当前应用程序上下文的环境。

  • getClassLoader ():获取用于加载类的类加载器。

  • getResourceLoader ():获取用于加载资源的资源加载器。

AnnotatedTypeMetadata

AnnotatedTypeMetadata 接口提供了对注解元数据的访问,包括获取类、方法或字段上的注解信息。通过 AnnotatedTypeMetadata,你可以获取与类、方法或字段相关的注解信息,以便在条件评估逻辑中做出相应的判断。

一些常用的方法包括:

  • isAnnotated (String annotationType):检查类、方法或字段是否被特定类型的注解所标注。

  • getAnnotationAttributes (String annotationType):获取特定类型的注解的属性值。

  • getMetaAnnotationAttributes (String annotationType):获取特定类型的注解上的元注解的属性值。

这个扩展暂时就到这了,后面如果有需求的话会加上实例啥的,现在主要是记录下笔记了解一下原理,暂时就不弄实例了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值