๐งฉ AOP Layer โ Aspects, Proxies & Crosscutting Logic Cheatsheet¶
Essence: The AOP Layer (Aspect-Oriented Programming) gives Spring its superpowers: it can intercept, extend, and wrap method calls at runtime โ adding behavior like transactions, security, caching, or logging transparently.
๐งญ 1. Concept Overview¶
Object-Oriented Programming (OOP) organizes what things are. Aspect-Oriented Programming (AOP) organizes what they do repeatedly across many places.
Without AOP:
public void transfer() {
startTransaction();
try {
doTransfer();
commit();
} catch (Exception e) {
rollback();
}
}
With AOP:
Spring inserts the transaction logic around your method automatically.
๐ช 2. What Is an Aspect?¶
An Aspect is a class that holds crosscutting logic โ code that applies to multiple classes or methods.
Core AOP Terms¶
| Term | Meaning | Example |
|---|---|---|
| Aspect | Class containing advice | @Aspect class LoggingAspect { ... } |
| Advice | The actual code that runs before/after a method | @Before, @After, @Around |
| Pointcut | Rule that selects which methods get intercepted | execution(* com.app..*(..)) |
| Join Point | A specific point in method execution where advice can run | Method call, exception |
| Proxy | Wrapper that intercepts and forwards method calls | Generated by Spring |
๐ง 3. How AOP Works in Spring¶
Your Bean (target)
โ
Spring detects AOP annotations
โ
Creates Proxy Bean (wrapper)
โ
Proxy intercepts method call
โ
Applies advice (before/after/around)
โ
Calls target method
Spring uses reflection and dynamic proxies to wrap your bean at runtime โ you never call the real object directly.
โ๏ธ 4. Declaring Aspects¶
Enable AOP in a configuration class:
Define an Aspect:
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.app.service.*.*(..))")
public void logBefore(JoinPoint jp) {
System.out.println("Method start: " + jp.getSignature());
}
@After("execution(* com.app.service.*.*(..))")
public void logAfter(JoinPoint jp) {
System.out.println("Method end: " + jp.getSignature());
}
}
๐งฉ 5. Types of Advice¶
| Advice Type | Annotation | When It Runs | Example |
|---|---|---|---|
| Before | @Before |
Before method call | Logging, auth checks |
| After | @After |
After method (success or fail) | Cleanup |
| AfterReturning | @AfterReturning |
Only after success | Metrics, caching |
| AfterThrowing | @AfterThrowing |
On exception | Error handling |
| Around | @Around |
Wraps the method call | Transactions, timing |
Example โ Around Advice¶
@Aspect
@Component
public class TimingAspect {
@Around("execution(* com.app..*(..))")
public Object measure(ProceedingJoinPoint jp) throws Throwable {
long start = System.nanoTime();
Object result = jp.proceed();
System.out.println(jp.getSignature() + " took " + (System.nanoTime() - start) + "ns");
return result;
}
}
โ๏ธ 6. Pointcut Expressions¶
The execution() designator defines where advice applies.
execution(modifiers-pattern? return-type-pattern declaring-type-pattern? method-name-pattern(param-pattern) throws-pattern?)
Examples:
execution(* com.app.service.*.*(..)) // all methods in package
execution(public * *(..)) // all public methods
execution(* transfer(..)) // any method named transfer
execution(* com.app..*(String)) // any method with String arg
Combine rules:
๐งฌ 7. Proxy Types โ How Spring Intercepts Calls¶
Spring AOP uses runtime proxies, not compile-time weaving.
| Proxy Type | Mechanism | Applies To | Library |
|---|---|---|---|
| JDK Dynamic Proxy | Implements interfaces | Interface-based beans | java.lang.reflect.Proxy |
| CGLIB Proxy | Subclasses the target class | Concrete classes (no interfaces) | Bytecode generation via CGLIB |
Spring decides automatically:
- If the bean implements an interface โ JDK proxy
- Otherwise โ CGLIB subclass
๐ JDK Proxy Example¶
MyService proxy = (MyService) Proxy.newProxyInstance(
clazz.getClassLoader(),
new Class[]{MyService.class},
(p, method, args) -> {
System.out.println("Before call");
return method.invoke(target, args);
});
๐ฌ CGLIB Example¶
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyService.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
System.out.println("Before " + method.getName());
return proxy.invokeSuper(obj, args);
});
MyService proxy = (MyService) enhancer.create();
๐งฑ 8. Built-In AOP Features in Spring¶
| Feature | Annotation | Underlying Mechanism |
|---|---|---|
| Transactions | @Transactional |
TransactionInterceptor via AOP |
| Asynchronous execution | @Async |
AsyncExecutionInterceptor |
| Caching | @Cacheable, @CachePut, @CacheEvict |
CacheInterceptor |
| Security | @PreAuthorize, @Secured |
MethodSecurityInterceptor |
| Retries | @Retryable |
RetryOperationsInterceptor |
All of these are implemented as aspects.
๐งฉ 9. AOP + IoC Integration Flow¶
1. Context starts
2. Spring scans beans
3. Detects @Aspect classes
4. Builds proxies for target beans
5. Replaces original bean references with proxy
6. Proxies intercept method calls
7. Calls proceed() โ executes target logic
From that moment, every call goes through the proxy pipeline.
โก 10. Common Pitfalls¶
| Problem | Cause | Fix |
|---|---|---|
| Advice not applied | Self-invocation (method calls inside same class) | Move method to another bean or use AspectJ compile-time weaving |
| AOP disabled | Missing @EnableAspectJAutoProxy |
Add in config |
| No proxy created | Final class/method | Remove final or use interface |
@Transactional not working |
Calling private/self method | Ensure proxy boundary |
| Order issues | Multiple aspects | Use @Order annotation |
๐ง 11. Debugging Proxies¶
Check whether a bean is proxied:
System.out.println(AopUtils.isAopProxy(bean)); // true/false
System.out.println(AopUtils.getTargetClass(bean));
Print proxy class:
System.out.println(bean.getClass()); // usually com.sun.proxy.$ProxyXX or CGLIB$$EnhancerBySpringCGLIB
๐งฎ 12. Custom Aspect Example โ Audit Logging¶
@Aspect
@Component
public class AuditAspect {
@Around("@annotation(Audit)")
public Object audit(ProceedingJoinPoint jp) throws Throwable {
System.out.println("AUDIT โ " + jp.getSignature());
return jp.proceed();
}
}
And annotation:
Now @Audit can be added to any method, and the aspect intercepts it.
๐งฉ 13. Performance Notes¶
- Proxy creation happens once at startup; not during runtime.
- Method interception adds minimal overhead (microseconds).
- Avoid deep proxy chains (e.g., multiple AOP frameworks stacked).
- Avoid applying AOP to ultra-hot code paths (like millions of calls/sec).
๐งญ 14. Quick Reference Summary¶
| Concept | Description | Spring Mechanism |
|---|---|---|
| Aspect | Class holding crosscutting logic | @Aspect |
| Advice | Code run before/after method | @Before, @After, etc. |
| Pointcut | Expression selecting join points | execution(...) |
| Proxy | Runtime wrapper intercepting calls | JDK / CGLIB |
| Join Point | Intercepted method execution | Method entry/exit |
| ProceedingJoinPoint | Around advice controller | proceed() executes real method |
| Aspect order | Order of execution | @Order(n) |
| AOP enablement | Activate AOP system | @EnableAspectJAutoProxy |
๐งฌ 15. Visual Summary¶
@Target Bean
โ
Detected by @Aspect processor
โ
Proxy Bean Created
โ
Method Call Intercepted
โ
@Before / @Around / @After
โ
Target Method Invoked
โ
Return to Caller
๐ Related¶
๐ช Core Takeaway¶
AOP turns Spring from a factory into an orchestra conductor. It doesnโt just create your objects โ it surrounds them with rhythm and timing. Through proxies, it can wrap logic around logic, making crosscutting behavior seamless and centralized. Reflection lets Spring see; IoC lets it build; AOP lets it intervene.