2V0-72.22 Exam Guide

Spring AOP on the 2V0-72.22: What Gets Tested and Why It Trips People Up

AOP is one of the domains where candidates lose the most points. The questions are not about knowing what AOP is — they test whether you understand how Spring's proxy-based implementation behaves in specific scenarios, and the edge cases that break assumptions.

Spring AOP is proxy-based, not bytecode manipulation

This is the most important thing to internalize. Spring AOP wraps your bean in a proxy. The proxy intercepts method calls and applies advice. Full AspectJ compiles advice into the bytecode directly — Spring does not. The exam exploits this difference repeatedly.

Spring uses one of two proxy mechanisms depending on the bean:

  • JDK dynamic proxy— used when the bean implements at least one interface. The proxy implements the same interface(s).
  • CGLIB proxy— used when there is no interface, or when proxyTargetClass = true is set. Creates a subclass at runtime.

CGLIB cannot subclass a final class. If a question shows a final class with an aspect applied — no proxy can be created, and AOP silently does nothing.

The self-invocation trap

This is the most commonly tested AOP scenario. When a bean calls one of its own methods internally, the call goes directly to this — bypassing the proxy entirely. No advice runs.

@Service
public class OrderService {

    public void placeOrder() {
        // This calls the real method directly, NOT through the proxy.
        // Any @Transactional or custom advice on processPayment() will NOT fire.
        this.processPayment();
    }

    @Transactional
    public void processPayment() {
        // ...
    }
}

The fix is to inject the bean into itself (@Autowired self-reference) or to restructure the code so the call goes through the proxy. The exam will show you code like the above and ask why the advice does not apply — the answer is always self-invocation.

Advice types — know the exact behavior of each

The exam distinguishes between advice types through scenario questions: “Which advice type can modify the return value?” or “Which advice fires even when an exception is thrown?”

AdviceWhen it runsCan stop execution?Can modify return?
@BeforeBefore methodOnly by throwingNo
@AfterReturningAfter successful returnNoNo (can read it)
@AfterThrowingWhen exception propagatesNoNo
@AfterAlways (like finally)NoNo
@AroundWraps the methodYes (skip proceed())Yes

The critical @Around trap: if your advice method does not call joinPoint.proceed(), the real method never executes. For non-void methods, the advice returns null (or the zero value for primitives). The exam will show this and ask what happens.

@Around("execution(* com.example.service.*.*(..))")
public Object logDuration(ProceedingJoinPoint joinPoint) throws Throwable {
    long start = System.currentTimeMillis();
    Object result = joinPoint.proceed(); // must call this
    long elapsed = System.currentTimeMillis() - start;
    log.info("Took {}ms", elapsed);
    return result; // must return this
}

Pointcut expressions — the most-tested syntax

Most exam questions on AOP involve reading or writing a pointcut expression. Focus on these designators:

// execution: matches method signatures — the most common
execution(* com.example.service.*.*(..))     // any method in service package (not subpackages)
execution(* com.example.service..*.*(..))    // any method in service and subpackages
execution(public * *(..))                    // any public method anywhere
execution(* *Service.find*(String))          // find* methods on *Service beans taking a String

// within: matches all methods in a type or package (no method-level filtering)
within(com.example.service.*)               // all types directly in the package
within(com.example.service..*)              // all types in the package and subpackages

// @annotation: matches methods with a specific annotation
@annotation(org.springframework.transaction.annotation.Transactional)

// @within: matches all methods in types that have a specific class-level annotation
@within(org.springframework.stereotype.Service)

// bean: matches a named Spring bean (Spring-specific, not in AspectJ)
bean(orderService)
bean(*Service)   // wildcard supported

Key distinction the exam tests: @annotation matches the annotation on the method. @within matches the annotation on the class. A method without @Transactional on a class annotated @Service is matched by @within(Service) but not by @annotation(Transactional).

Pointcuts can be combined:

// && (and), || (or), ! (not)
execution(* com.example.service.*.*(..)) && @annotation(Transactional)
execution(* com.example.*.*(..)) && !within(com.example.internal.*)

Aspect ordering with @Order

When multiple aspects apply to the same join point, their order matters. @Order controls it — lower value means higher priority.

@Aspect
@Order(1)   // runs first (outermost in the call stack)
@Component
public class SecurityAspect { ... }

@Aspect
@Order(2)   // runs second
@Component
public class LoggingAspect { ... }

For @Before: order 1 fires before order 2. For @After and @AfterReturning: order 1 fires after order 2 (it wraps the other, so it unwinds last). Think of it as nested try/finally blocks — the outermost aspect is the first to enter and the last to exit.

Configuration — what the exam expects you to know

@Configuration
@EnableAspectJAutoProxy                    // enables AOP proxy creation
// @EnableAspectJAutoProxy(proxyTargetClass = true)  // force CGLIB for all beans
public class AppConfig { }

@Aspect       // marks this as an aspect — NOT a bean by itself
@Component    // still needed for Spring to pick it up
public class MyAspect {

    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceLayer() {}     // reusable pointcut

    @Before("serviceLayer()")
    public void beforeService(JoinPoint joinPoint) {
        // joinPoint.getSignature(), joinPoint.getArgs(), etc.
    }
}

Note: @Aspect alone does not register the class as a Spring bean. You still need @Component (or an explicit bean definition) for Spring to manage it. The exam tests this combination.

Quick reference: what the exam actually asks

  • — A final class with an aspect: AOP does not apply (CGLIB cannot subclass it)
  • this.method() inside a Spring bean: advice does not fire (self-invocation bypasses proxy)
  • @Around without proceed(): original method never runs
  • — Private method with a pointcut: not intercepted (proxies can only intercept public methods)
  • within(com.example.service.*) vs within(com.example.service..*): single * excludes subpackages, double ..* includes them
  • @annotation vs @within: method-level annotation vs class-level annotation
  • — Lower @Order value = higher priority = outermost aspect in the call stack

Practice AOP questions in exam conditions

PrepForge mock exams include AOP scenarios drawn from real exam patterns — timed, with full explanations.

Start a Mock Exam