Spring AOP

Basic Spring
≈ 2 min read

Logic that is needed in many places at once

Logging, timing, access checks, or transaction management may be needed by dozens of methods. If this technical logic is written inside every service, business code quickly gets mixed with infrastructure. AOP lets you describe that behavior separately and apply it to selected method calls.

@Aspect
@Component
class TimingAspect {

    @Around("execution(* com.example.service..*(..))")
    Object measure(ProceedingJoinPoint joinPoint) throws Throwable {
        long started = System.nanoTime();

        try {
            return joinPoint.proceed();
        } finally {
            long elapsed = System.nanoTime() - started;
            System.out.println(elapsed);
        }
    }
}

The measure() method contains advice — code that runs around a matching call. The expression in @Around defines a pointcut: which methods should match this rule. joinPoint.proceed() passes control to the original method.

What AOP gives you

The main benefit is separation of responsibilities. A service stays focused on its own job, while repetitive technical logic lives separately and is connected with one rule.

AOP is for cross-cutting logic, not every kind of repetition. If behavior is part of the class's domain responsibility, it is usually better to express it with normal methods, objects, and composition instead of hiding it inside an aspect.

Spring AOP applies such behavior not “inside the method bytecode,” but through an intermediary object. To read AOP, transactions, and other Spring features correctly, the next step is to understand proxies.