Five core Spring AOP concepts every Java developer should know.
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 methods2. @Before
Runs before the target method.
Before
↓
Actual MethodExample
@Before("serviceMethods()")
public void before(JoinPoint jp) {
System.out.println("Calling " + jp.getSignature());
}Suppose
service.saveUser();Console
Calling saveUser()
Actual saveUser() executesUses
- Logging
- Authentication
- Authorization
- Validation
3. @After
Runs after the method finishes, whether it succeeds or throws an exception.
Before
↓
Method
↓
AfterExample
@After("serviceMethods()")
public void after(JoinPoint jp) {
System.out.println("Finished");
}Success
Before
Method
AfterException
Before
Method throws Exception
After4. @AfterReturning
Runs only if the method returns successfully.
Method Success
↓
AfterReturningExample
@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 JohnIf exception occurs
throw new RuntimeException();Nothing executes.
5. @AfterThrowing
Runs only if the method throws an exception.
Method
↓
Exception
↓
AfterThrowingExample
@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 BalanceIf 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
@AroundSuccessful 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");
}
}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
│
▼
RepositoryAOP 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
CleanupThis 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.






