为什么 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 文件中相同的方式构建配置,例如:(cfg
和 cfgA
是两个不同配置层次结构的 "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 {
}
给出下面的示例,我预计 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 文件中相同的方式构建配置,例如:(cfg
和 cfgA
是两个不同配置层次结构的 "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 {
}