为什么 spring beans 即使条件表明它不应加载到上下文中也会被验证?

Why are spring beans validated even if the condition says it should not be loaded into the context?

给出下面的示例,我预计 MyConfig.getSrvConfig() 不会被调用,因此也不会对返回的对象执行任何验证。 但是由于某种原因执行了验证并且测试用例失败了。这个设置有什么问题吗?

我知道如果我在声明时没有初始化 private MySrvConfigBean srvConfig 测试会通过 - 但我真的不希望 MySrvConfigBean 成为一个独立的 class 和 @ConfigurationProperties(prefix = "cfg.srvConfig") 注释。

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = { TestCaseConfiguration.class })
public class ConditionalConfigValidationTest {

    @Autowired
    private ApplicationContext applicationContext;

    @Test
    public void test() {
        assertNotNull(applicationContext);
        assertFalse("srvConfig must NOT be in context", applicationContext.containsBean("srvConfig"));
    }

    @Configuration
    @EnableConfigurationProperties(value = { MyConfig.class })
    public static class TestCaseConfiguration {
    }

    @Component
    @Validated
    @ConfigurationProperties(prefix = "cfg")
    public static class MyConfig {
        private MySrvConfigBean srvConfig = new MySrvConfigBean();

        @Bean
        @Valid
        @Conditional(MyCondition.class)
        public MySrvConfigBean getSrvConfig() {
            return srvConfig;
        }

        public static class MySrvConfigBean {

            @NotNull
            private String name;

            public String getName() {
                return name;
            }
        }
    }

    public static class MyCondition implements Condition {
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            return false;
        }
    }
}

我们希望采用这种方式的原因是,因为这样我们就可以在代码中以与在 YAML 文件中相同的方式构建配置,例如:(cfgcfgA 是两个不同配置层次结构的 "root" 对象)。

cfg:
  srvConfig: 
    name: Dude
  clientConfig: 
    xxx: true
    yyy: Muster
cfgA:
  aaaConfig:
    bbb: false
    ccc: Dundy
  dddConfig:  
    fff: 3

感觉验证的执行(由 getSrvConfig() 上的 @Valid 触发)在这种情况下是一个错误。

显然这是 not supported 并且应该以不同的方式解决:

@Configuration
@Conditional(MyCondition.class)
@EnableConfigurationProperties(value = { MyConfig.class })
public static class TestCaseConfiguration {
}