Spring框架条件装配详解

后端 潘老师 3个月前 (11-30) 71 ℃ (0) 扫码查看

本文主要讲解关于Spring框架条件装配详解相关内容,让我们来一起学习下吧!

什么是条件装配?

从语文的角度出发,解读条件装配四个字,就是根据某种条件装配,再结合我们对Spring FrameWork的理解,我们就不难得知,条件装配就是Spring FramwWork允许根据特定条件来选择性地装配和配置Bean。

条件装配有哪些形式?

  • 基于@Profile 的条件装配
  • 基础@Conditional 的条件装配

最主要就是基于这两种形式的条件装配形式,当然@Conditional也扩展了相当多更为细致的条件装配注解。

基于@Profile的条件装配

理解Profile

首先,我们翻译一下这个单词,在我们软件开发中,这个单词的意思是配置文件。那说到配置文件,我想大家应该是不会陌生的,我们的Spring项目都会有一个application.yml或者是application.properties文件,这二者其一就是我们的配置文件。再细化一点说,profile是用来定义和配置不同环境或场景下的应用程序行为和设置的文件或机制。它用于在不同的运行环境中提供不同的配置选项,以满足特定的场景需求。简单说就是,区分dev,prod,test环境。

@Profile的使用

通过刚刚对profile的理解,我们基本就可以知道它是用于控制我们整体的项目环境的。

 @Target({ElementType.TYPE, ElementType.METHOD})
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 @Conditional(ProfileCondition.class)
 public @interface Profile {
 ​
     /**
      * The set of profiles for which the annotated component should be registered.
      */
     String[] value();
 ​
 }
  • String[] value():这是@Profile注解的属性。它表示应该注册注解组件的一组配置文件。

下面,我们思考一下根据不同的环境注入不同的bean?当然就是最直接简单的做法就是使用我们的@Profile注解了。下面是简易的代码示例:

 @Profile("test")
 @Component
 public class A {
 }
  • 这是一个简易的Bean,我们给他标注@Profile注解,标注它只有在test环境下才会被注入IOC容器

下面是目前的环境:

 spring:
   application:
     name: spring-demo
   profiles:
     active: dev
  • 现在我们是dev环境

这个时候我们直接启动我们的Spring程序,尝试获取Bean

 @SpringBootApplication
 public class SpringDemoApplication {
 ​
     public static void main(String[] args) {
         ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args);
         A a = context.getBean(A.class);
         System.out.println(a);
     }
 ​
 }
 ​
 //下面是输出的异常信息
 Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.zgq.springdemo.spring.demo.entity.A' available
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
     at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1186)
     at com.zgq.springdemo.SpringDemoApplication.main(SpringDemoApplication.java:14)
  • 从输出结果,我们可以看到我们无法从IOC容器中获取到这个Bean,其实就可以知道是我们的@Profile注解起到了作用,控制住了我们Bean的注入

接下来我们将环境调整到test环境

 spring:
   application:
     name: spring-demo
   profiles:
     active: test

再次启动我们的Spring程序,我们得到以下结果

 com.zgq.springdemo.spring.demo.entity.A@11841b15
  • 这个时候,我们的Bean就得以正确注入了

当然,配置环境的方式不止这一种,只是这一种我们最为常用,此外,profile最主要的作用其实还是控制我们整个项目的环境。

基于@Conditional的装配

这个相较于@Profile控制整个项目环境,@Conditional更为细致,主要是用来控制某个Bean的注入

理解Conditional

我们直接百度翻译这个单词就可以知道,这个单词的意思是有条件的,那我们再结合对Spring FrameWork的理解,不难得知,这个注解的作用就是让被其标注的Bean要注册到IOC容器时,必须满足注解上标注的条件

@Conditional的使用

 @Target({ElementType.TYPE, ElementType.METHOD})
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 public @interface Conditional {
 ​
     /**
      * All {@link Condition} classes that must {@linkplain Condition#matches match}
      * in order for the component to be registered.
      */
     Class<? extends Condition>[] value();
 ​
 }
  • Class<? extends Condition>[] value():这是@Conditional注解的属性。它表示一个Condition类的数组,这些类必须匹配才能注册组件(Bean)

下面我们还是以一个简单的代码示例,解析一下该如何使用

 @Component
 @Conditional(value = {ExistACondition.class})
 public class B {
 }
 ​
 ​
 public class ExistACondition implements Condition {
     @Override
     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
         return context.getBeanFactory().containsBeanDefinition(A.class.getName());
     }
 }
  • 这里简单实现一下Condition接口,当存在A这个类的Bean对象的时候,我们才会注入B这个类的Bean对象

那我们将刚刚的环境改回dev环境,这个时候容器中就是没有A这个类的Bean对象的,此时我们直接启动我们的Spring程序,输出结果如下

 Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.zgq.springdemo.spring.demo.entity.B' available
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
     at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1186)
     at com.zgq.springdemo.SpringDemoApplication.main(SpringDemoApplication.java:22)
  • 可见,这个时候也是无法注入B这个类的Bean对象的

@ConditionalOnxxx系列注解

@ConditionalOnxxx系列注解是Spring Boot中常用的条件注解,用于基于特定条件进行自动配置。下面是一些@ConditionalOnxxx系列注解的示例:

  1. @ConditionalOnClass:当类路径中存在指定的类时,才生效配置。
 @Configuration
 @ConditionalOnClass(DataSource.class)
 public class DataSourceConfiguration {
     // 当类路径中存在DataSource类时,才会执行该配置类
     // 可以在这里创建和配置数据源的相关Bean
 }
  1. @ConditionalOnMissingClass:当类路径中缺少指定的类时,才生效配置。
 @Configuration
 @ConditionalOnMissingClass("org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType")
 public class DatabaseConfiguration {
     // 当类路径中缺少EmbeddedDatabaseType类时,才会执行该配置类
     // 可以在这里创建和配置数据库相关的Bean
 }
  1. @ConditionalOnBean:当容器中存在指定的Bean时,才生效配置。
 @Configuration
 @ConditionalOnBean(DataSource.class)
 public class TransactionConfiguration {
     // 当容器中存在DataSource类型的Bean时,才会执行该配置类
     // 可以在这里创建和配置事务相关的Bean
 }
  1. @ConditionalOnMissingBean:当容器中缺少指定的Bean时,才生效配置。
 @Configuration
 @ConditionalOnMissingBean(DataSource.class)
 public class EmbeddedDatabaseConfiguration {
     // 当容器中缺少DataSource类型的Bean时,才会执行该配置类
     // 可以在这里创建和配置内嵌数据库相关的Bean
 }

5.@ConditionalOnProperty注解的示例:

 @Configuration
 @ConditionalOnProperty(
     value = "app.feature.enabled",
     havingValue = "true",
     matchIfMissing = true
 )
 public class FeatureConfiguration {
     // 当名为"app.feature.enabled"的配置属性值为"true"时,才会执行该配置类
     // 可以在这里创建和配置与特定功能相关的Bean
 }

在上述示例中,@ConditionalOnProperty注解的value属性指定了要检查的属性键,即"app.feature.enabled"havingValue属性指定了属性值应该与其匹配的期望值,即"true"matchIfMissing属性指定如果未定义该属性,则条件是否满足,默认为true,表示如果缺少该属性,也满足条件。

因此,在这个例子中,当应用程序配置中的app.feature.enabled属性值为true时,才会执行FeatureConfiguration配置类。如果该属性未定义或其值不为true,并且matchIfMissing属性设置为true,那么条件也将满足。

这些是@ConditionalOnxxx系列注解的一些示例,它们可以根据特定的条件决定是否应用特定的配置类。通过使用这些条件注解,您可以根据应用程序的环境和配置情况来自动配置和调整Spring Boot应用程序的行为。

总结

条件装配是Spring Framework中的一个特性,它允许根据特定条件选择性地装配和配置Bean。条件装配有两种形式:基于@Profile和基于@Conditional@Profile用于定义和配置不同环境或场景下的应用程序行为和设置,而@Conditional用于控制某个Bean的注入,要求满足指定条件才会注册到IOC容器中。这些条件注解可以根据项目需求灵活运用,例如基于类的存在、Bean的存在或属性的值等。

以上就是关于Spring框架条件装配详解相关的全部内容,希望对你有帮助。欢迎持续关注潘子夜个人博客(www.panziye.com),学习愉快哦!


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/12029.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】