博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot基础篇Bean之条件注入@Condition使用姿势
阅读量:4031 次
发布时间:2019-05-24

本文共 3420 字,大约阅读时间需要 11 分钟。

前面几篇关于Bean的基础博文中,主要集中在Bean的定义和使用,但实际的情况中有没有一些场景是不加载我定义的bean,或者只有满足某些前提条件的时候才加载我定义的Bean呢?

本篇博文将主要介绍bean的加载中,条件注解@Conditional的相关使用

I. @Conditional注解

这个注解在Spring4中引入,其主要作用就是判断条件是否满足,从而决定是否初始化并向容器注册Bean

1. 定义

@Conditional注解定义如下,其内部主要就是利用了Condition接口,来判断是否满足条件,从而决定是否需要加载Bean

@Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Conditional {    Class
[] value();}

下面是Condtion接口的定义,这个可以说是最基础的入口了,其他的所有条件注解,归根结底,都是通过实现这个接口进行扩展的

@FunctionalInterfacepublic interface Condition {    boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);}

这个接口中,有个参数比较有意思ConditionContext,它持有不少有用的对象,可以用来获取很多系统相关的信息,来丰富条件判断,接口定义如下

public interface ConditionContext {    // 获取Bean定义    BeanDefinitionRegistry getRegistry();    // 获取Bean工程,因此就可以获取容器中的所有bean    @Nullable    ConfigurableListableBeanFactory getBeanFactory();    // environment 持有所有的配置信息    Environment getEnvironment();        // 资源信息    ResourceLoader getResourceLoader();    // 类加载信息    @Nullable    ClassLoader getClassLoader();}

2. 使用说明

通过一个小例子,简单的说一下如何使用Condition和@Conditional注解,来实现bean的条件加载

首先我们定义一个随机产生数据的类,其功能就是随机生成一些数据

public class RandDataComponent
{ private Supplier
rand; public RandDataComponent(Supplier
rand) { this.rand = rand; } public T rand() { return rand.get(); }}

我们目前提供两种随机数据生成的bean,但是需要根据配置来选择具体选中的方式,因此我们如下定义Bean

@Configurationpublic class ConditionalAutoConfig {    @Bean    @Conditional(RandIntCondition.class)    public RandDataComponent
randIntComponent() { return new RandDataComponent<>(() -> { Random random = new Random(); return random.nextInt(1024); }); } @Bean @Conditional(RandBooleanCondition.class) public RandDataComponent
randBooleanComponent() { return new RandDataComponent<>(() -> { Random random = new Random(); return random.nextBoolean(); }); }}

上面的配置,先不管@Conditional注解的内容,单看两个Bean的定义,一个是定义int随机数生成;一个是定义boolean随机生成;

但是我们的系统中,只需要一个随机数据生成器即可,我们选择根据配置conditional.rand.type的值来选择到底用哪个,配置如下

# int 表示选择随机产生int数据; 非int 表示随机产生boolean数据conditional.rand.type=int

接下来就得看这个条件如何加上了,也就是上面配置类ConditionalAutoConfig中两个注解的内容了,两个类都是实现Condition的接口,具体如下

public class RandBooleanCondition implements Condition {    @Override    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {        String type = conditionContext.getEnvironment().getProperty("conditional.rand.type");        return "boolean".equalsIgnoreCase(type);    }}public class RandIntCondition implements Condition {    @Override    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {        String type = conditionContext.getEnvironment().getProperty("conditional.rand.type");        return "int".equalsIgnoreCase(type);    }}

上面的实现也比较清晰,获取配置值,然后判断,并返回true/fase;返回true,则表示这个条件满足,那么这个Bean就可以被加载了;否则这个Bean就不会创建

3. 测试与验证

针对上面的配置与实现,写一个测试类如下

@RestController@RequestMapping(path = "/conditional")public class ConditionalRest {    @Autowired    private RandDataComponent randDataComponent;    @GetMapping(path = "/show")    public String show() {        String type = environment.getProperty("conditional.rand.type");        return randDataComponent.rand() + " >>> " + type;    }}

当配置文件的值为int时,每次访问返回的应该都是正整数,演示如下图

将配置的值改成boolean之后,再次测试如下图

 

转载地址:http://ywgbi.baihongyu.com/

你可能感兴趣的文章
慢慢欣赏linux 内核符号
查看>>
慢慢欣赏linux if_changed_xxx的作用
查看>>
慢慢欣赏linux kbuild构建
查看>>
慢慢欣赏linux phy驱动初始化
查看>>
慢慢欣赏linux phy设备配置
查看>>
grub学习(1) 第一阶段启动
查看>>
c语言位域分配原则
查看>>
linux内核学习(1)第一阶段启动 解压缩内核
查看>>
grub学习(2) 加载内核
查看>>
grub学习(3) 加载initrd
查看>>
grub学习(4) 启动linux内核
查看>>
编译链接学习笔记1
查看>>
编译链接学习笔记2
查看>>
x86_64汇编语言
查看>>
慢慢欣赏linux kbuild的一些技巧
查看>>
慢慢欣赏linux kbuild如何编译c和汇编
查看>>
C对象化
查看>>
慢慢欣赏linux 生成内核镜像
查看>>
慢慢欣赏linux 内核反汇编分析
查看>>
慢慢欣赏linux 内核的重定位
查看>>