0
点赞
收藏
分享

微信扫一扫

Spring Boot 2 实战:根据条件来自动配置不同逻辑的Bean

DT_M 2022-04-06 阅读 15


Spring Boot 2 实战:根据条件来自动配置不同逻辑的Bean_spring


文章目录

  • ​​1. 前言​​
  • ​​2. @Conditional 注解​​
  • ​​2.1 Class Conditions​​
  • ​​2.2 Bean Conditions​​
  • ​​2.3 Property Conditions​​
  • ​​2.4 Resource Conditions​​
  • ​​2.5 Web Application Conditions​​
  • ​​2.6 SpEL Expression Conditions​​
  • ​​3. 自定义 Condition​​
  • ​​4. 总结​​


1. 前言

我们经常会有根据条件来加载不同的接口。比如你查询目录下文件列表, ​Windows​ 下你会用 ​​CMD​​ 的 ​​dir​​ 命令,而 ​Linux​ 下你会使用 ​​ls​​ 命令。 熟悉 ​Spring Boot​ 自动配置的也知道 ​Spring Boot​ 能根据不同的实际情况启用不同的配置。这就是​​@Conditional​​注解在发挥作用。

该注解指定了在什么条件下创建 ​Bean​ 进行配置。

2. @Conditional 注解

Spring Boot​ 包含多个 ​​@Conditional​​​ 注释,可以在​​@Configuration​​​注解的类和​​@Bean​​​注解方法中使用。​​@Conditional​​​类型的注解,可以注解在类上,可以注解在​​Bean​​方法上,可以允许基于Spring Environment属性包含配置,可以仅允许在存在特定资源时包含配置。也可自定义,接下来我们来熟悉一下 Spring Boot 提供的一些具体的条件注解。

2.1 Class Conditions

​@ConditionalOnClass​​​和​​@ConditionalOnMissingClass​​ 两个在类上的注解:

判断指定的类是否存在来构建自动配置,也可使用​​name​​属性名来指定类名。

2.2 Bean Conditions

​@ConditionalOnBean​​​和​​@ConditionalOnMissingBean​​ 两个在 ​Bean​ 方法上的注解:

判断指定的 Bean 是否存在来构建自动配置,可以使用​​value​​属性来按类型或名称(id)指定 ​Bean​, 可以使用​​search​​属性指定 ​ApplicationContext​ 层次结构来搜索​​Bean​​。

@Configuration
public class MyAutoConfiguration {

@Bean
@ConditionalOnMissingBean
public MyService myService() { ... }

}

要添加注意添加 Bean 时的顺序,官方建议在自动配置类上仅使用 ​​@ConditionalOnBean​​​和​​@ConditionalOnMissingBean​​注释,因为可以保证这些注释在添加用户定义的Bean后执行。

​@ConditionalOnBean​​​和​​@ConditionalOnMissingBean​​​注解作用在​​@Configuration​​​注释的类上,等同于在作用在每个包含​​@Bean​​的方法上。

2.3 Property Conditions

​@ConditionalOnProperty​​​注解可以基于Spring Environment属性包含的配置进判断,再决定自动配置的执行,使用 ​​prefix​​​ 和 ​​name​​ 属性指定应检查的属性。默认情况下,匹配​存在​且不等于​false​的任何属性。 您还可以使用​​havingValue​​​和​​matchIfMissing​​属性创建更高级的检查。

2.4 Resource Conditions

​@ConditionalOnResource​​注释仅允许在存在特定资源时执行自动配置。 可以使用常用的 Spring 约定来指定资源,如以下示例所示:file:/home/user/test.dat。

2.5 Web Application Conditions

​@ConditionalOnWebApplication​​​和​​@ConditionalOnNotWebApplication​​​注解用于判断应用程序是否为​​Web应用程序​​,Web应用程序是使用​Spring WebApplicationContext​,定义会话范围或具有​StandardServletEnvironment​的任何应用程序。

2.6 SpEL Expression Conditions

​@ConditionalOnExpression​​注解允许根据​SpEL​表达式的结果来执行配置。

3. 自定义 Condition

如果上面几种都不能满足你的需要。那么我们可以通过实现​​Condition​​​接口,并重写其​​matches​​方法来构造判断条件。

  • 1.实现 Condition 接口来定义判断条件
//Windows系统的判断条件
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class WindowsCondition implements Condition {

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("os.name").contains("Windows");
}
}


//Linux系统的判断条件
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class LinuxCondition implements Condition {

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("os.name").contains("Linux");
}
}
  • 2.实现不同系统下的Bean类
//接口
public interface ListService {

public String showListCmd();
}

//Windows下的实现类
public class WindowsListServiceImpl implements ListService {

@Override
public String showListCmd() {
return "dir";
}
}

//Linux下的实现类
public class LinuxListServiceImpl implements ListService {

@Override
public String showListCmd() {
return "ls";
}
}
  • 3.配置类

@Conditional​注解调用条件判断的类并根据返回的结果来创建​​Bean​

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ConditionConfig {

@Bean
@Conditional(WindowsCondition.class)
public ListService windowsListService() {
return new WindowsListServiceImpl();
}

@Bean
@Conditional(LinuxCondition.class)
public ListService linuxListService() {
return new LinuxListServiceImpl();
}
}
  • 4.运行类
@RunWith(SpringRunner.class)
@SpringBootTest

public class SecurityLearningApplicationTests {

@Resource
private ListService listService ;
@Resource
private ApplicationContext context;




public void testCondition(){
System.out.println(context.getEnvironment().getProperty("os.name")
"系统下的列表命令:"
listService.showListCmd());
}

}

4. 总结

今天我们对 ​Spring Boot​ 中的 ​Condition​ 条件判断注入进行了系统性的了解。不仅对 ​Spring Boot​ 提供的一些开箱即用的 ​Condition​ 进行了学习,还实现了自定义的 ​Condition​ 。如果你要对 ​Spring Boot​ 的自动配置深入学习或者根据业务来灵活定制,就必须对 ​Condition​ 进行系统性的学习。

​关注公众号:Felordcn获取更多资讯​



举报

相关推荐

0 条评论