When you inject a List<T> of beans, how do you control their order, and how do @Order, the Ordered interface, and orderedStream() relate?
answer
- Lower @Order value = earlier / higher precedence
- @Order default = LOWEST_PRECEDENCE (Integer.MAX_VALUE) = last
- Ordered.getOrder() = programmatic equivalent
- orderedStream() ranks; stream() does not
- @Order ≠ bean creation order; ≠ single-value disambiguation
basics
~20 sAdd @Order(n) to each bean or implement Ordered.getOrder(). Spring sorts injected List/Set/array by that value — lower number = higher priority = earlier. For ObjectProvider use orderedStream(), which applies the same ranking; plain stream() does not.
solid answer
~40 sFor array, List, and Set injection Spring ranks the beans using the @Order annotation, the Ordered interface, or JSR-250 @Priority — a **lower** value means higher precedence and an earlier position. @Order's default is Ordered.LOWEST_PRECEDENCE (Integer.MAX_VALUE), so un-annotated beans go last. Ordered is the programmatic equivalent (getOrder()). This matters for handler chains, filters, validators — anything order-sensitive. With ObjectProvider<T>, orderedStream() returns candidates in this ranked order, whereas stream() returns them in registration order with no guarantee. Note @Order on a @Bean/@Component only affects collection-injection and stream ordering; it does NOT change bean creation order or startup sequence, and it does not decide @Primary/autowire disambiguation for a single-valued injection.
code
java · 21 linespublic interface Step { void apply(Ctx c); }
@Component @Order(Ordered.HIGHEST_PRECEDENCE) // runs first
class ValidateStep implements Step { public void apply(Ctx c){} }
@Component @Order(10)
class EnrichStep implements Step { public void apply(Ctx c){} }
@Component // no @Order → LOWEST_PRECEDENCE → runs last
class PersistStep implements Step { public void apply(Ctx c){} }
@Service
class Pipeline {
private final ObjectProvider<Step> steps;
Pipeline(ObjectProvider<Step> steps) { this.steps = steps; }
void run(Ctx c) {
// orderedStream() honors @Order: Validate -> Enrich -> Persist
steps.orderedStream().forEach(s -> s.apply(c));
}
}go deeper
Know @Order/Ordered rank injected lists and lower = first.
Explain the default LOWEST_PRECEDENCE, orderedStream vs stream, and that @Order isn't creation order.
Distinguish @Order (collection ordering) from @Priority's role in primary selection and framework-specific ordering.
Design deterministic pipelines, discuss ordering constants, and where subsystem-specific ordering overrides plain injection ranking.
## Controlling collection order When order matters — a chain of `Filter`s, `Validator`s, event `Handler`s — you rank the beans so the injected `List` comes out in the sequence you want. ### The three ranking mechanisms 1. **`@org.springframework.core.annotation.Order(int)`** — annotation on the class or `@Bean` method. 2. **`org.springframework.core.Ordered`** — interface with `int getOrder()`; programmatic, useful when the order is computed. 3. **`@jakarta.annotation.Priority(int)`** (JSR-250) — also honored for collection ordering. ### Lower = earlier Ordering is **ascending**: the smallest value has the highest precedence and appears **first**. Constants help: `Ordered.HIGHEST_PRECEDENCE = Integer.MIN_VALUE`, `Ordered.LOWEST_PRECEDENCE = Integer.MAX_VALUE`. `@Order`'s **default value is `LOWEST_PRECEDENCE`**, so a bean without `@Order` sorts to the end. ```java @Component @Order(1) class AuthFilter implements ChainFilter {} @Component @Order(2) class RateLimitFilter implements ChainFilter {} @Component class LoggingFilter implements ChainFilter {} // LOWEST → last @Service class Chain { Chain(List<ChainFilter> filters) { /* [Auth, RateLimit, Logging] */ } } ``` ### What gets ordered - **Arrays, `List`, `Collection`, `Set`** injection points are sorted. - **`Map<String,T>`** is keyed, not positionally sorted, though it reflects the same resolution order in its `LinkedHashMap`. - **`ObjectProvider<T>.orderedStream()`** applies the same ranking lazily; **`stream()`** does **not** — it yields registration order. ### Critical scoping of @Order - `@Order` affects **collection/stream injection ordering only**. It is a common misconception that it controls **bean instantiation/startup order** — it does not (use `@DependsOn` for creation ordering). - `@Order` does **not** resolve single-valued autowiring ambiguity. If two candidates match a plain `T` injection, `@Order` won't pick one — you still get `NoUniqueBeanDefinitionException` unless you use `@Primary`/`@Qualifier`. (`@Priority`, however, *does* influence single-value primary selection — but disambiguation belongs to the qualifier/primary topic.) ### @Order on classes vs @Bean methods Both work: annotate the `@Component` class, or put `@Order` on the `@Bean` factory method in a `@Configuration` class. For beans you don't own, the `@Bean`-method placement is how you rank them. ### Gotcha: framework-specific ordering Some Spring subsystems have their **own** ordering rules (e.g., servlet `Filter` registration order, `@WebFilter`, Spring Security filter chain). Plain `@Order`-driven `List` injection ranking applies to your own collections; don't assume it governs every framework hook. ### When to use - Deterministic pipelines/chains where sequence changes behavior. - Prefer `orderedStream()` on `ObjectProvider` when you want ranking plus lazy evaluation or optional emptiness.
- Does @Order control the order in which the beans are instantiated at startup?No. @Order only affects the ordering of collection/stream injection. Bean creation order is driven by dependency graph and @DependsOn, not @Order.
- What is the difference between ObjectProvider.stream() and orderedStream()?orderedStream() returns candidates sorted by @Order/Ordered/@Priority; stream() returns them in registration order with no ordering guarantee.
saying these in an interview costs you the question
- Thinking higher @Order number means earlier position
- Believing @Order controls bean instantiation/startup order
- Assuming plain stream() is ordered like orderedStream()
- Claiming @Order resolves single-valued autowire ambiguity