spring-boot条件配置——conditionContext

发布时间:2022-07-05 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了spring-boot条件配置——conditionContext脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

前言

前几天,我们在剖析sPRing boot启动过程的时候,提到了一个比较核心的组件——condITionContext,这个组件的作用是,根据特定的条件,对bean进行依赖配置。这么说有点拗口,下面我们同一些具体的实例看下conditionCOntext到底是如何工作的。

条件配置

conditionContext初始化

开始实例之前,我们先看下conditionContext的初始化过程,首先它是在创建容器的时候被初始化化的,更准确地说是在创建AnnotatedBeanDefinitionReader实例的时候被初始的:

spring-boot条件配置——conditionContext

这里实例化的是ConditionContextImpl,它是条件配置接口的实现类,它的初始化过程也就是一些基本属性的赋值,包括容器(registry)、bean工厂、环境配置(environment)、资加载器(resourceLoader)、类加载器(classLoader),它的5个核心方法分别就是这5个属性的获取方法,所以我们也不再过多说明。

需要注意的是,这里的ConditionContextImpl实现类是一个内部实现类。

由于ConditionContextImpl中并没有条件配置的相关方法,所以我们需要研究另一个持有ConditionContextImpl的组件——ConditionEvaluator。这个类名的意思是条件评估者,官方注释的意思是:评估条件注解的内部类。

spring-boot条件配置——conditionContext

下面是这个类的核心方法shouldSkip

spring-boot条件配置——conditionContext

从这个类的shouldSkip方法中,我们可以得到几个核心的内容:

  • @Conditional注解:条件配置最核心的注解之一,这个注解需要一个或多个继承了Condition接口的参数

    spring-boot条件配置——conditionContext

    这个Condition接口有一个matches方法,这个方法的返回值最终决定是否可以对当前类进行注册配置,如果同时有多个Conditon,则需要所有Condition返回true才能对当前类进行注册配置。

  • 在创建bean的时候,会根据shouldSkip判断是否进行bean的初始化和注册:

    spring-boot条件配置——conditionContext

    如果shouldSkip返回true,则会直接跳过该类的初始化,shouldSkip要返回true,则condition的返回值必须为false:

    spring-boot条件配置——conditionContext

    条件配置实例

    下面我们通过一个具体实例来演示下条件配置的具体用法。

    定义条件

    首先我们需要定义一个条件,也就是实现Conditon接口:

    public class ResultCondition implements Condition {
        @override
        public boolean matches(ConditionContext context, AnnotatedTyPEMetadata metadata) {
            Boolean matches = true;
            System.out.println("ResultCondition matches =" + matches);
            return matches;
        }
    }
    

    这里为了演示方便,我直接返回true

    增加配置类

    在配置类中,我加了一个Result的实例化配置,同时在它的配置上增加了 @Conditional(ResultCondition.class)

    @configuration
    public class ConditionConfig {
        private final LOGger logger = LoggerFactory.getLogger(ConditionConfig.class);
    
        @Conditional(ResultCondition.class)
        @Bean
        public Result result() {
            logger.info("condition result");
            return new Result();
        }
    }
    

    加了这个注解之后,想要Result实例化成功,就要求ResultConditionmatches方法必须为true,也就是shouldSkip返回false

    测试

    下面我们简单测试下,因为我已经在相关代码中加了打印输出,所以我们直接启动看效果即可,当matches方法返回true时,我们可以看到Result的实例化配置被执行了:

    spring-boot条件配置——conditionContext

    然后我们把matches方法返回值改成false再看下,这时候我们会发现Result的实例化配置并没有被执行:

    spring-boot条件配置——conditionContext

    综上,我们可以看出来,conditionContext其实就是通过Condition接口来实现有条件的配置,这样的好处是,可以动态地调整优化配置,即灵活又方便,更重要的是,这种方式还可以有效降低组件的耦合性,便于扩展,而且可以提高系统启动效率(condition可以直接过滤不需要实例化的组件)。

    举个栗子,比如你现在要开发一个集成组件,这个组件既可以发消息,又可以做redis的工具包,还可以做zk的客户端,这时候如果别人要用你这个集成组件中的某一个功能,比如发消息的功能,在没有条件配置的情况下,他不仅需要引入消息组件的依赖,还需要引入zkredis的组件依赖,但是对他而言,后两种组件是非必要的,引入之后只会增加不必要的依赖和配置,但是没有这些依赖和配置又会报错,所以极其不灵活。

    但是如果你的组件才有的是条件配置的话,就不会存在这个问题,你可以通过条件配置的方式,来启用相关组件:他引入消息组件依赖,你启用消息组件配置;他启用zk依赖,你启用zk组件配置;他启用redis组件依赖,你启用redis组件配置。当不存在相关组件依赖时,相关组件配置并不会起作用。

    知识扩展

    除了我们这里说的@Conditional注解外, spring boot还为我们提供了 @ConditionalOnClass注解,这个注解的作用是当指定的类的class存在于classpath中时,才会执行该配置,和我们Conditional注解差不多,他只是已经默认实现了matches方法,我们直接可以使用。

    类似的注解还有很多,有兴趣的小伙伴可以自己去看下:

    spring-boot条件配置——conditionContext

    关于@ConditionalOnClass注解的用法,可以参考我们前面分享过的spring-boot-starter自定义相关内容:

总结

好了,关于conditionContext的相关内容我们就先讲到这里,感兴趣的小伙伴自己可以去看下我们今天提到的其他注解。

下面做一个简单小结,今天我们围绕着conditionContext的初始化过程,探讨了spring boot条件化配置的基本原理,然后我们还通过一个简单实例演示了条件配置的具体用法,最后我们还对@Conditional注解的基础上做了一点点引申和扩展,总体来说,条件配置的用法还是比较简单的,但是如果真正用起来,是可以有效降低你的系统的耦合性,极大提高系统扩展性。

脚本宝典总结

以上是脚本宝典为你收集整理的spring-boot条件配置——conditionContext全部内容,希望文章能够帮你解决spring-boot条件配置——conditionContext所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。