早期我们曾使用 @Profile("!prepub")
控制预发环境不执行定时任务,后面又有需求需要让开发环境也不执行定时任务,于是将表达式改为了 @Profile("!dev & !prepub")
,随即发现环境控制不生效了,所有环境都在执行定时任务。然后我又测试了表达式 @Profile("daily | product")
, 发现也不生效,于是简单跟了下源码,在此简单记录。
首先根据 Profile (Spring Framework API) 的文档,我们知道:
A profile expression allows for more complicated profile logic to be expressed, for example “p1 & p2”. See Profiles.of(String…) for more details about supported formats.
即在配置中可以使用表达式,比如 p1 & p2
,在 Profiles (Spring Framework API) 中还给出了其他表达式的示例。
但是在我们的场景中,为何配置没有生效呢,通过跟踪源码,发现在我们的应用环境中,处理 @Profile
注解时会进入 ConditionEvaluator.java at v4.3.16.RELEASE 中的如下代码:
1 | /** |
随即调用至 ProfileCondition.java at v4.3.16.RELEASE:
1 | /** |
继续跟踪源码,调用至 AbstractEnvironment.java at v4.3.16.RELEASE:
1 |
|
看到这里就清楚了,源码中仅有处理 !
开头的 profile
的逻辑,并没有处理多个表达式的逻辑,导致我们写的表达式都被当作单个 profile
进行处理,从而使预想的逻辑没有生效,然后检查了下 AbstractEnvironment
类的提交记录,发现表达式支持自 Spring 5.1.0 开始提供,而我们使用的 Spring 版本为 4.3.16,表达式支持的代码提交位于:Add profile expression support · spring-projects/spring-framework@e2623b7 · GitHub。
再仔细查看之前提到的 Profile (Spring Framework API) 与 Profiles (Spring Framework API) 的文档,发现 Profile
的文档中 since 为 3.1,而 Profiles
的文档中 since 为 5.1,而表达式的例子在 Profile
中就提供了,从而使我们误以为自 3.1 开始就支持,导致了该问题,最后我们将配置调整为 @Profile({"daily", "product"})
解决了该问题。
附上 @Profile
判断逻辑的调用栈帧:
1 | "RMI TCP Connection(2)-127.0.0.1@1847" daemon prio=5 tid=0x14 nid=NA runnable |