I came across a case where beans resolved with context.getBeanProvider(MyService.class)
are not ordered as they should, when:
* there is a parent/child context setup
* beans are ordered with @Order
The following sample application reproduces the problem
public class ContextTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
parent.register(DefaultConfig.class);
parent.register(CustomService.class);
AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
child.setParent(parent);
child.register(DefaultConfig.class);
parent.refresh();
child.refresh();
child.getBeanProvider(MyService.class).orderedStream().forEach(service -> {
System.out.println(service.getClass().getSimpleName());
// CustomService (order -1) should be before DefaultService (order 0)
// prints beans in the wrong order: DefaultService, CustomService
});
}
interface MyService { }
static class CustomService implements MyService { }
static class DefaultService implements MyService { }
@Configuration
static class CustomConfig {
@Bean
@Order(-1)
CustomService customService() {
return new CustomService();
}
}
@Configuration
static class DefaultConfig {
@Bean
@Order(0)
DefaultService defaultService() {
return new DefaultService();
}
}
}
Note that this problem doesn't happen if beans implement Ordered
instead of being annotated with @Order
.
Comment From: snicoll
So the problem is that FactoryAwareOrderSourceProvider
has a check to verify that the instance is present in the local bean factory: https://github.com/spring-projects/spring-framework/blob/b88695a36eec16aa5315a842ab551f284aaab089/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java#L2152
In the case of the CustomService
, it is only defined in the parent so that check fails and no source is made available. I wonder if that's an oversight, considering that getMergedLocalBeanDefinition
looks up in the parent.
Comment From: snicoll
I've looked at this one with @jhoeller and we believe that looking the bean definition in the parent is what we should be doing for consistency.
Current status is available in https://github.com/snicoll/spring-framework/commit/e425825cc2061ef2e089a2c285ecc18b61c9f402.
Comment From: rishiraj88
Very interesting issue! 👍