1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

spring-boot条件配置——conditionContext

前言

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

条件配置

conditionContext初始化

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

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

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

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

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

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

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

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

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

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

    条件配置实例

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

    定义条件

    首先我们需要定义一个条件,也就是实现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的实例化配置被执行了:

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

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

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

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

    知识扩展

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

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

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

总结

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

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

posted @ 2021-09-24 13:11  云中志  阅读(192)  评论(0编辑  收藏  举报