Sitemap

Five core Spring AOP concepts every Java developer should know.

3 min readJul 30, 2026

--

1. @Pointcut

A Pointcut defines which methods should be intercepted.

It does not execute any code by itself.

@Pointcut("execution(* org.xyz.service..*(..))")
public void serviceMethods() {}

Meaning

execution(
* -> Any return type
org.xyz.service.. -> Any class in service package
*(..) -> Any method with any parameters
)

Now you can reuse it:

@Before("serviceMethods()")

instead of

@Before("execution(* org.xyz.service..*(..))")

Think of Pointcut like a Filter

                All Methods
│
│
+-----------+-----------+
| |
service package controller package
│ │
│ │
Pointcut picks these methods

2. @Before

Runs before the target method.

Before
↓
Actual Method

Example

@Before("serviceMethods()")
public void before(JoinPoint jp) {
System.out.println("Calling " + jp.getSignature());
}

Suppose

service.saveUser();

Console

Calling saveUser()

Actual saveUser() executes

Uses

  • Logging
  • Authentication
  • Authorization
  • Validation

3. @After

Runs after the method finishes, whether it succeeds or throws an exception.

Before
↓
Method
↓
After

Example

@After("serviceMethods()")
public void after(JoinPoint jp) {
System.out.println("Finished");
}

Success

Before

Method

After

Exception

Before

Method throws Exception

After

4. @AfterReturning

Runs only if the method returns successfully.

Method Success
↓
AfterReturning

Example

@AfterReturning(
pointcut="serviceMethods()",
returning="result")
public void afterReturning(
JoinPoint jp,
Object result) {

System.out.println(result);
}

Suppose

public String getUser() {
return "John";
}

Console

Method executes

Returned John

If exception occurs

throw new RuntimeException();

Nothing executes.

5. @AfterThrowing

Runs only if the method throws an exception.

Method
↓
Exception
↓
AfterThrowing

Example

@AfterThrowing(
pointcut="serviceMethods()",
throwing="ex")
public void logException(
JoinPoint jp,
Exception ex) {

System.out.println(ex.getMessage());
}

Suppose

public void payment() {
throw new RuntimeException("Insufficient Balance");
}

Console

Insufficient Balance

If no exception occurs

Get Ravi Jaisawal’s stories in your inbox

Join Medium for free to get updates from this writer.

Nothing executes.

Complete Flow

Suppose you have

@Before
@AfterReturning
@AfterThrowing
@After
@Around

Successful execution

Around (before)

↓

Before

↓

Actual Method

↓

AfterReturning

↓

After

↓

Around (finally)

Exception execution

Around (before)

↓

Before

↓

Actual Method

↓

AfterThrowing

↓

After

↓

Around (finally)

Around (finally) is not a Spring AOP annotation. It refers to the finally block inside your @Around advice.

Consider this code:

@Around("applicationMethods()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

long start = System.currentTimeMillis();

try {
System.out.println("Before method");

// Execute the actual method
return joinPoint.proceed();

} finally {
// Always executes
long end = System.currentTimeMillis();
System.out.println("Execution Time: " + (end - start) + " ms");
}
}
Press enter or click to view image in full size

When to use each

  • @Pointcut: Define reusable method selection logic.
  • @Before: Validate requests, authenticate users, or log method entry.
  • @After: Perform cleanup that should happen regardless of success or failure.
  • @AfterReturning: Log or inspect successful return values, update metrics.
  • @AfterThrowing: Log exceptions, trigger alerts, or convert exceptions if appropriate.

Real Example: Order Placement

Imagine an online shopping application.

Customer clicks

"Place Order"

Flow:

Client
│
▼
Controller
│
▼
Service
│
▼
Repository

AOP execution:

              Request arrives
│
▼
@Before
Validate JWT
Validate Request
Log Request
│
▼
Controller.placeOrder()
│
▼
Service.placeOrder()
│
▼
Repository.save()
│
▼
Success?
/ \
Yes No
│ │
▼ ▼
@AfterReturning @AfterThrowing
Update Metrics Log Exception
Publish Event Send Alert
│ │
└────┬────┘
▼
@After
Clear ThreadLocal
Release Lock
Cleanup
Press enter or click to view image in full size

This is how Spring AOP is commonly applied in production systems at large-scale organizations: @Before protects and validates requests, @After guarantees cleanup, @AfterReturning reacts to successful business operations, and @AfterThrowing centralizes failure handling without scattering that logic across every service method.

--

--

Ravi Jaisawal
Ravi Jaisawal

Written by Ravi Jaisawal

Lead Software Engineer with 12+ years of experience architecting and delivering scalable, cloud-native distributed systems and enterprise platforms.