skip to content

How does the throwing attribute work, and how do you filter @AfterThrowing to a specific exception type?

level: middleimportance: should knowfreq 55%

answer

  1. throwing = param NAME
  2. declared type = the filter
  3. assignable-to → advice fires
  4. Throwable catches Errors too
  5. name mismatch → startup failure

basics

~20 s

The throwing attribute names the advice method parameter that receives the thrown exception. Declaring that parameter as a specific type (e.g. DataAccessException) makes the advice fire only when the thrown exception is that type or a subtype.

solid answer

~40 s

`@AfterThrowing(throwing = "ex")` tells Spring to bind the exception thrown by the join point to the advice method parameter named `ex`. The declared type of that parameter acts as a filter: Spring only invokes the advice if the thrown exception is *assignable to* that type. So `void onError(DataAccessException ex)` runs only for `DataAccessException` and its subclasses; other exceptions propagate without triggering this advice. If you declare it as `Throwable` or `Exception`, it catches essentially everything (a `Throwable` param also catches `Error`s). The parameter name in the method must exactly match the `throwing` value. You can also add a `JoinPoint` parameter to get signature/args. This type-narrowing is the idiomatic way to scope after-throwing advice to a category of failures rather than filtering inside the method body.

code

java · 9 lines
java
@Aspect
@Component
public class DbFailureAspect {
    // Only fires for DataAccessException and its subclasses
    @AfterThrowing(pointcut = "execution(* com.example.repo.*.*(..))", throwing = "ex")
    public void onDbError(JoinPoint jp, DataAccessException ex) {
        // handle only DB-layer failures; other exceptions won't trigger this
    }
}

go deeper

for a junior

Knows throwing binds the exception to a parameter.

for a middle

Explains type narrowing as the filter mechanism and name-matching rule.

for a senior

Discusses multiple typed advices, argNames, and JoinPoint vs ProceedingJoinPoint.

for a principal

Weighs typed narrowing vs pointcut design for failure taxonomy.

### The `throwing` attribute `@AfterThrowing` has a `throwing` attribute whose value is the **name of the advice-method parameter** that should receive the exception thrown by the join point. It is a *binding*, exactly analogous to `returning` on `@AfterReturning`. ```java @AfterThrowing(pointcut = "serviceMethods()", throwing = "ex") public void onFailure(JoinPoint jp, DataAccessException ex) { ... } ``` Here `throwing = "ex"` matches the parameter named `ex`. The name must match **exactly** — a mismatch causes an `IllegalArgumentException` at startup/weaving time (binding cannot be resolved). ### Type narrowing = filtering The **declared type** of the bound parameter is itself a filter. Spring only calls the advice when the thrown exception **is assignable to** (is-an-instance-of) the declared type: - `Throwable ex` → matches every throwable, including `Error`. - `Exception ex` → all exceptions (checked + unchecked), but not `Error`. - `RuntimeException ex` → only unchecked exceptions. - `DataAccessException ex` → only Spring data-access exceptions and subclasses. So you scope which failures fire the advice *by declaring the parameter type*, not by an `instanceof` check in the body. This is cleaner and lets you have multiple advices for different exception families. ### Getting context You can combine the exception binding with a `JoinPoint` parameter (must be first) to access `jp.getSignature()`, `jp.getArgs()`, `jp.getTarget()`, etc. You cannot use `ProceedingJoinPoint` here — that is exclusive to `@Around`. ### Edge cases and gotchas - **Parameter-name matching**: `throwing` binds by *name*. With Spring's default parameter-name discovery (compiled with `-parameters` or debug info, or via `argNames`) this resolves; otherwise you may need `argNames`. - **Multiple after-throwing advices**: you can define several, each narrowed to a different type; all whose type matches will run (order controlled by `@Order`/`Ordered`). - **It still doesn't swallow**: even a narrowly-typed advice only observes; the exception continues to propagate. - **Kotlin**: same rules; declare the parameter with the target throwable type. ### When to use Narrow the type when you only care about a specific failure category — e.g., log only `DataAccessException` for DB-layer monitoring, or only your domain's `BusinessException`.

  • If you declare the parameter as Throwable versus Exception, what's the difference in matching?
    Throwable also matches Errors (e.g. OutOfMemoryError, assertion errors), while Exception matches only checked and unchecked Exceptions, not Errors.
  • What happens if the throwing attribute name doesn't match any parameter?
    Binding fails and Spring throws an IllegalArgumentException when it builds the advisor (effectively a startup/weaving error).

saying these in an interview costs you the question

  • Thinking throwing is the exception's class name rather than the parameter name
  • Believing you must use instanceof inside the body to filter by type

context