How does the throwing attribute work, and how do you filter @AfterThrowing to a specific exception type?
answer
- throwing = param NAME
- declared type = the filter
- assignable-to → advice fires
- Throwable catches Errors too
- name mismatch → startup failure
basics
~20 sThe 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@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
Knows throwing binds the exception to a parameter.
Explains type narrowing as the filter mechanism and name-matching rule.
Discusses multiple typed advices, argNames, and JoinPoint vs ProceedingJoinPoint.
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