章
目
录
本文主要讲解关于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
系列注解的示例:
@ConditionalOnClass
:当类路径中存在指定的类时,才生效配置。
@Configuration
@ConditionalOnClass(DataSource.class)
public class DataSourceConfiguration {
// 当类路径中存在DataSource类时,才会执行该配置类
// 可以在这里创建和配置数据源的相关Bean
}
@ConditionalOnMissingClass
:当类路径中缺少指定的类时,才生效配置。
@Configuration
@ConditionalOnMissingClass("org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType")
public class DatabaseConfiguration {
// 当类路径中缺少EmbeddedDatabaseType类时,才会执行该配置类
// 可以在这里创建和配置数据库相关的Bean
}
@ConditionalOnBean
:当容器中存在指定的Bean时,才生效配置。
@Configuration
@ConditionalOnBean(DataSource.class)
public class TransactionConfiguration {
// 当容器中存在DataSource类型的Bean时,才会执行该配置类
// 可以在这里创建和配置事务相关的Bean
}
@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),学习愉快哦!