Spring AOP vs AspectJ — what are the differences? — Cracked Java
// Spring Framework & Spring Boot · AOP & Proxies
SeniorTheoryBig Tech

Spring AOP vs AspectJ — what are the differences?

Spring AOP and AspectJ share syntax — the @Aspect, @Around, execution(...) annotations — but are completely different mechanisms. Spring AOP is a lightweight, proxy-based, runtime framework that intercepts method calls on Spring beans. AspectJ is a full AOP language with its own bytecode weaver that can instrument almost anything. Confusing them is a classic interview trap, because Spring AOP reuses AspectJ's pointcut grammar without being AspectJ.

The core differences

Spring AOPAspectJ
MechanismDynamic proxies (JDK/CGLIB)Bytecode weaving
WhenRuntime, at bean creationCompile-time (CTW) or load-time (LTW)
JoinpointsMethod execution onlyMethods, constructors, field get/set, static init, …
ScopeSpring-managed beans onlyAny object, any class
Self-invocationBypassed (proxy not involved)Caught (woven into the code itself)
SetupZero — built into SpringNeeds ajc compiler or a weaving agent
PerformanceSlight per-call proxy overheadNear-native; cost paid once at weave time

Why proxy-based AOP is limited

A proxy wraps the target object from the outside. It can only see calls that arrive through it — i.e. external method invocations on Spring beans. It cannot intercept:

  • A method calling another method on this (self-invocation).
  • private, final, or static methods.
  • Field reads/writes.
  • Objects you created with new instead of getting from the container.
@Service
class OrderService {
    @Transactional
    public void save() { ... }

    public void process() {
        save();   // self-call: Spring AOP misses the @Transactional entirely
    }
}

With AspectJ, the advice is woven into the bytecode of save() itself, so it fires no matter how the method is reached — even via this.save().

When to use which

Use Spring AOP for the 95% case: transactions, security, caching, logging on your service layer. It's zero-config and good enough.

Reach for AspectJ when you need what proxies can't give: intercepting field access, advising non-Spring objects (e.g. domain entities created with new), catching self-invocation, or advising final/private methods. Enable it via load-time weaving (@EnableLoadTimeWeaving + agent) or compile-time weaving with the AspectJ compiler.

Mark your status