Using latest Spring-Boot 3.x, I experimented a bit with @Order in the context of Spring-Security on multiple @SecurityFilterChains.
I created 2 @Configuration SecurityConfigs, each one with 2 @Bean SecurityFilterChain, and later on I debugged the
@Autowired(required = false)
void setFilterChains(List<SecurityFilterChain> securityFilterChains) {
this.securityFilterChains = securityFilterChains;
}
to double-check the injection order.
-
- When annotating explictly (with random different @Order values) all the bean-exposing methods, injection is eventually always ordered, regardless the instantiation order, as docs state, and regardless the @Order annotations at class-level.
-
- When annotating only the classes, the annotations do not change the instantiation order of both @Configuration classes or its bean-exposing methods, nor the order of injection of those beans.
So I am wondering, what is the point of @Order at class level?
-
- Is it doing something or it is expected to not have any effect? Does it depend on the annotated kind of component? (Perhaps it's useless on @Configurations but not on @EventListeners, etc.. If so I think it would be nice to have it documented
-
- Am I perhaps facing a bug? If so I'll create the issue in this github or spring-security one if hat's the culprit
-
- A very important relevant nuance that should be documented in my opinion is whether the @Order annotation is that kind of annotation that when put at class level behaves like an alias for annotating all its methods, or on the contrary, it has semantics on its own. If so, I think they should be documented for @Configuration classes context at least
Thanks a lot!
Comment From: cloudshiftchris
Which classes were you annotating? The @Order
annotation needs to be on the bean classes themselves; in the case of Spring Security it provides the implementations of SecurityFilterChain
which necessitates ordering outside of the bean implementation (that you cannot change, and there are multiple builder-created instances of) using @Order
on the bean factory methods.
Comment From: cloudshiftchris
When @Order
is on @Configuration
classes it orders those configuration classes and does not pertain to ordering of beans defined within them.
Comment From: bclozel
I think @cloudshiftchris is right, @Order
is mainly supported on components (as stated in its Javadoc):
@Order
defines the sort order for an annotated component. ... NOTE: Since Spring 4.0, annotation-based ordering is supported for many kinds of components in Spring, even for collection injection where the order values of the target components are taken into account (either from their target class or from their@Bean
method). While such order values may influence priorities at injection points, please be aware that they do not influence singleton startup order which is an orthogonal concern determined by dependency relationships and@DependsOn
declarations (influencing a runtime-determined dependency graph).
Additionally, this annotation is supported on @Configuration
classes to influence the ordering of their processing (between "top-level" configuration classes and between nested configuration classes); see #17257 and #19947.
I think we can document this behavior a bit better, especially in the reference documentation. I would not emphasize this feature, as absolute ordering is hard to maintain for such cases and all the other means (@Import
, auto-configuration ordering in Spring Boot) is a better choice.
Comment From: nightswimmings
@cloudshiftchris @bclozel In my manual tests, annotating @configuration classes with @Order did not alter the instantiation order of them or its bean-exposing methods, nor the order of injection of those beans when fetched as a list, but Ill repeat the test, since the version I played with is now half-year old
Comment From: cloudshiftchris
@nightswimmings you wouldn't be able to readily discern the effects of @Order
on @Configuration
as it happens at processing time (creation of bean definitions), not instantiation time.
@Order
on @Configuration
classes is used to control the order they are processed (and, as @bclozel noted, is discouraged as it is fragile). For example, using @ConditionalOnMissingBean
may require that a configuration class is ordered after other ones that may create that bean (use @AutoConfigureAfter
or other mechanisms instead).
@Order
has no bearing on instantiation order. Beans (@Configuration
classes are beans themselves) are instantiated from the inferred dependency graph.
When @Order
is used on @Bean
definitions or on bean classes themselves it affects the ordering for collection injection (as is desired for Spring Security filters).
For Spring Security filters the correct method to order them is @Order
on @Bean
. The only alternative method I'm aware of is to decorate the returned SecurityWebFilter with one that implements the Ordered
interface (I've had to do this to address #30849 )