问题
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