问题
I have a Spring @Configuration class that should register a bean when a specific property value is set in the environment. I wrote a custom Condition implementation that checked whether the value was present, and it works when I fire up the application in Spring Boot, but the bean was never registered when running JUnit tests. I debugged the application and determined that the Condition was being evaluated before the PropertySourcesPlaceholderConfigurer was being instantiated.
I modified my Condition to implement ConfigurationCondition and specify evaluation during the REGISTER_BEAN phase. The method is still called before the configurer is instantiated, but the registered bean now comes and goes as I add or remove the property from the properties file.
Is this the best way to reorder the evaluation? Is this what the ConfigurationCondition interface is for, or am I just accidentally getting it to work now?
@Conditional(PropertyCondition.class)
@Configuration
public class PostbackUrlConfiguration {
@Value("${serviceName.postbackUrl}")
String postbackUrl;
@Bean
public PostbackUrlProvider provider() {
return new FixedUrlProvider(postbackUrl);
}
}
public class PropertyCondition implements ConfigurationCondition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().containsProperty("serviceName.postbackUrl");
}
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.REGISTER_BEAN;
}
}
The test configuration is a static class on my test case:
@Configuration
@ComponentScan
@PropertySource("classpath:/postback.properties")
@Import(PostbackUrlConfiguration.class)
public static class TestConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
回答1:
The parsing phase for a @Configuration class involves reading its class definition, populating a collection of Configuration objects (because one @Configuration class may @Import another @Configuration class so these imports are parsed as well), processing @PropertySources, @ImportResources etc.
Processing @PropertySources doesn't, also, load those properties yet. After the parsing phase is done, the @PropertySources properties are loaded. After these are loaded, then the beans' definitions from inside @Configuration classes are registered (REGISTER_BEAN phase).
So, what you see using a ConfigurationCondition with ConfigurationPhase.REGISTER_BEAN phase is expected because those properties are actually available in the Environment at the time when beans' definitions are registered and after the @Configuration class has been parsed.
Using just a Condition I believe it doesn't even reach the parsing phase of a @Configuration, the evaluation is done even before that, when the @Configuration class definition is to be registered.
来源:https://stackoverflow.com/questions/23526643/how-do-i-delay-evaluation-of-a-spring-conditional-configuration-annotation