skip to content

Aspect Ordering: @Order / Ordered

@Order or the Ordered interface decides which aspect wraps which when several match one join point, lowest value outermost, with before and after advice nesting accordingly. Asked whenever a scenario stacks logging, security and transactions on the same method.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

Explain what 'the aspect with the lowest order value has the highest precedence' means for the execution of before advice versus after advice across two aspects.

level: middleimportance: must knowfreq 50%

answer

  1. onion rings, target at centre
  2. before = ascending, after = descending
  3. outermost first in, last out
  4. @Around wraps both legs at proceed()

basics

~20 s

The lowest-value aspect is outermost, like the outer layer of an onion. On the way in, its @Before runs first. On the way out, its @After runs last. So before advice runs highest-precedence-first, and after advice runs highest-precedence-last (reversed).

solid answer

~40 s

Precedence maps to nesting depth. The aspect with the lowest @Order value is the outermost wrapper; the highest value is innermost, closest to the target. Entering the call, control flows outer to inner, so @Before advice executes in ascending order of value (highest precedence first). Leaving the call, control unwinds inner to outer, so @After, @AfterReturning, and @AfterThrowing execute in descending order (highest precedence last). @Around advice sees both legs: the outermost @Around wraps everything, and whatever it does before proceed() runs first while what it does after proceed() runs last. This is the classic 'before highest first, after lowest first' rule. A practical consequence: a security aspect you want to gate entry AND clean up last should be given the lowest value so it is truly outermost.

code

java · 18 lines
java
@Aspect @Component @Order(1)
class OuterAspect {
    @Before("execution(* svc.*(..))") void before() { System.out.println("outer before"); }
    @AfterReturning("execution(* svc.*(..))") void after() { System.out.println("outer after"); }
}

@Aspect @Component @Order(2)
class InnerAspect {
    @Before("execution(* svc.*(..))") void before() { System.out.println("inner before"); }
    @AfterReturning("execution(* svc.*(..))") void after() { System.out.println("inner after"); }
}

// Output for one matched call:
// outer before
// inner before
// <target runs>
// inner after
// outer after

go deeper

for a junior

Grasp the 'lowest value runs first' half and the onion image.

for a middle

Must state both legs correctly: before ascending, after descending.

for a senior

Explains @Around's two legs and why symmetric bracketing is desirable.

for a principal

Uses ordering deliberately to guarantee resource lifecycles (open first / close last) across concerns.

## Mental model: nested layers Picture the target method at the centre and each matching aspect as a concentric ring. **Precedence = how far out the ring is.** Lowest `@Order` value → outermost ring; highest value → innermost ring, hugging the target. Execution walks *inward* to reach the target, then unwinds *outward*: ``` Order(1) before -> Order(2) before -> [TARGET] -> Order(2) after -> Order(1) after ``` ## The two rules - **Before-type advice (`@Before`, and the pre-`proceed()` part of `@Around`)** runs from **highest precedence to lowest** — i.e. ascending order value. Outermost first. - **After-type advice (`@After`, `@AfterReturning`, `@AfterThrowing`, and the post-`proceed()` part of `@Around`)** runs from **lowest precedence to highest** — i.e. descending order value. Outermost **last**. So `@Order(1)` runs its `before` first and its `after` last; `@Order(2)` runs its `before` second and its `after` first. This symmetry is exactly what you want: whatever set up context first tears it down last. ## @Around and proceed() An `@Around` method receives a `ProceedingJoinPoint` and must call `pjp.proceed()` to invoke the next layer (another aspect or the target). Code before `proceed()` behaves like `@Before`; code after behaves like `@After`. The outermost `@Around` therefore fully encloses inner aspects and the target. ## Worked example With `SecurityAspect @Order(1)` and `TxAspect @Order(2)` both matching `save()`: 1. Security `@Before` (open security context) 2. Tx `@Before` (begin transaction) 3. `save()` executes 4. Tx `@AfterReturning` (commit) 5. Security `@AfterReturning` (audit success) Security is outermost, so it brackets the transaction entirely. If you swapped the values, the transaction would bracket security — usually wrong. ## Gotchas - The 'first' intuition only holds for the *before* leg; people forget the after leg reverses. - Ordering applies **between** aspects. Ordering **within** one aspect (multiple advice methods in the same class) is a separate, trickier topic. - Equal order values leave the tie unresolved — avoid duplicate values for aspects that interact.

  • For @Around advice, which part behaves like @Before and which like @After?
    Code before pjp.proceed() behaves like @Before (runs on the way in); code after proceed() behaves like @After (runs on the way out). The outermost @Around wraps all inner aspects and the target.
  • If two interacting aspects accidentally share the same @Order value, what happens?
    The tie is unresolved — their relative order becomes undefined again. Give interacting aspects distinct values.

saying these in an interview costs you the question

  • Saying after advice also runs highest-precedence-first (it reverses)
  • Believing highest order value is outermost
  • Thinking @Around only affects the before leg

context

open as a page

You have two Spring aspects that both match the same method call. By default, which one runs first, and how do you control the order?

level: juniorimportance: should knowfreq 55%

basics

~20 s

By default the order is undefined. To make it deterministic, give each aspect a precedence: annotate the aspect class with @Order(n) or implement the Ordered interface. The aspect with the lower number runs first (outermost).

open as a page

A teammate annotates individual @Before methods with @Order to sequence them and is confused when nothing changes. What's going on, and what would you tell them?

level: seniorimportance: should knowfreq 25%

basics

~20 s

@Order controls precedence between aspect beans, not between advice methods. On a method it's ignored for AOP ordering. To sequence steps, put them in separate aspect classes and order those, or combine them into one advice method.

open as a page

Two advice methods declared in the same @Aspect class both apply to one join point. What determines their relative order, and how has Spring's behaviour here changed?

level: seniorimportance: should knowfreq 35%

basics

~20 s

You cannot order two advice methods within the same aspect via @Order — it only works between aspects. Historically the order was undefined (reflection can't recover source order). Since Spring 5.2.7 they're ordered by advice type: @Around, @Before, @After, @AfterReturning, @AfterThrowing.

open as a page

How would you reason about ordering a custom auditing or security aspect relative to Spring's own transaction management on the same service method?

level: principalimportance: nice to knowfreq 20%

basics

~20 s

Decide which concern must bracket the others and give it the lowest order value so it's outermost. Spring's transaction advice has its own configurable order (default lowest precedence / Integer.MAX_VALUE), so an aspect with a lower value runs outside the transaction; a higher value runs inside it.

open as a page