I have two AutoConfiguration classes, with an ordering dependency defined via @AutoConfigureBefore
but no direct dependency between them (setting up some legacy libraries that have not great static initialization and implicit static dependencies between themselves).
I have also added @AutoConfigurationOrder
trying to resolve that and observed the same behaviors. I left that out in my sample.
In the absence of any dependency, the two autoconfigurations run in the order defined by the @AutoConfigureBefore
and the components are successfully instantiated.
However, if any component in the app adds a dependency on a component from the second autoconfiguration, that component is created and injected before any components in the first autoconfiguration are created.
This repo demonstrates the failure case:
https://github.com/cfieber/autoconfig-order see https://github.com/cfieber/autoconfig-order/blob/master/bootapp/src/test/java/bootapp/BreakyTest.java specifically
Observed on both spring-boot 2.2.6.RELEASE
and 2.3.1.RELEASE
I believe I can work around this problem by making the initializing component in the first autoconfiguration a bean post processor or something to cause it to initialize early, however that feels a bit heavy handed and less obvious than expressing the dependency with the autoconfiguration orderings.
The two autoconfigurations do not have direct dependencies (or even @DependsOn
references) because there are a few different ways to configure the first dependency so I don't want a direct reference there.
Comment From: snicoll
@cfieber thanks for the report and the sample.
My expectation is that if AutoConfiguration @Configuration classes express relationships between each other via @AutoConfigureBefore or @AutoConfigureAfter that @Beans in one @Configuration will be created before @Beans in the other.
That's the wrong expectation. The auto-configuration order is about BeanDefinition
registration, not actual bean instantiation. If, for instance, you want to create a bean if a bean of a certain type is not present, this order makes sure that the context knows about any bean definition that matches @ConditionalOnMissingBean
. There is no guarantee whatsoever that beans in auto-configuration A will be fully created an initialized before beans in auto-configuration B. If the user configuration has a dependency on a bean in auto-configuration B, the context will instantiate it to honour that requirement as well as any dependency that is required at that point.
If some initialization order is required, you need to tell the context via @DependsOn
or asking the context to inject the bean that needs to be created first.
Comment From: wilkinsona
I think we should improve the javadoc of the @AutoConfigureBefore
, @AutoConfigureAfter
, and @AutoConfigureOrder
annotations. The current javadoc talks about the annotations controlling the order in which the auto-configuration is applied, but does not define what it means to be applied.
Comment From: cfieber
thanks so much for the quick response!