Loslegen
Javaneer
Zurück zur Stufe
Modul 0·Spring-Grundlagen

Aspektorientierte Programmierung

Querschnittsbelange wie Logging, Sicherheit und Transaktionen mit Aspekten, Advice und Springs Proxys herauslösen.

18 Min. LesezeitExperte

Deutsche Übersetzung in Arbeit

Diese Lektion ist noch nicht ins Deutsche übersetzt und wird daher auf Englisch angezeigt. Der Rest der Seite ist vollständig lokalisiert.

Auf dieser Seite

Some concerns don't belong to any single class - they cut across many of them. Logging, security checks, performance timing, and transaction management need to happen in dozens of methods, yet they have nothing to do with those methods' actual jobs. Scatter that code everywhere and you get noise, duplication, and drift.

Aspect-Oriented Programming (AOP) lets you write such a concern once and have Spring apply it across many methods automatically.

A concern that cuts across every room

Think of a building's fire-sprinkler system. Fire safety isn't the job of the kitchen, the office, or the lobby - yet every room needs it. You don't install a bespoke sprinkler inside each desk; you run one system across the whole building. AOP is that cross-cutting system for your code: define the concern once, and it covers every method you point it at.

The vocabulary

Four terms unlock every AOP discussion:

  • Aspect - the module holding a cross-cutting concern (e.g. "timing").
  • Advice - the code to run (before, after, or around a method).
  • Join point - a place where advice could apply (a method call).
  • Pointcut - an expression selecting which join points to advise.

An aspect in action

Here's a timing aspect that logs how long selected methods take - without touching a single one of them:

@Aspect
@Component
class TimingAspect {

    // pointcut: any method in the service package
    @Around("execution(* com.bookvault.service..*(..))")
    Object time(ProceedingJoinPoint call) throws Throwable {
        long start = System.nanoTime();
        try {
            return call.proceed();                 // run the real method
        } finally {
            long ms = (System.nanoTime() - start) / 1_000_000;
            log.info("{} took {} ms", call.getSignature(), ms);
        }
    }
}

Every method under com.bookvault.service is now timed. Add a new service tomorrow and it's timed too - zero extra code. The service classes stay blissfully unaware.

How Spring does it: proxies

Remember from the container lesson that because Spring hands out your beans, it can hand out enhanced ones. That's exactly what happens here. Spring wraps the target bean in a proxy - a stand-in object with the same interface. Callers get the proxy; it runs the advice, then delegates to the real bean.

The IoC container wiring a bean graphYou declare the components; the container instantiates them in dependency order and injects each one. Wire it step by step.
ApplicationContext
BookController — not created yet
injects BookService
BookService — not created yet
injects BookRepository
BookRepository — not created yet
injects DataSource
DataSource — not created yet

Nothing exists yet — you've only written the classes and their dependencies.

0 / 4 beans wired

Proxies only intercept external calls

Because the proxy sits around the bean, advice runs only when a call comes in from outside. If a bean calls its own method internally (this.otherMethod()), the call skips the proxy - so the advice (and @Transactional!) won't fire. This "self-invocation" gotcha catches everyone once.

The AOP you'll use constantly

You'll rarely write aspects day to day - but you'll use them everywhere, because Spring's most important features are built on AOP:

  • @Transactional wraps a method in a database transaction (Data module).
  • @Cacheable caches a method's result.
  • @Async runs a method on another thread.
  • Method security (@PreAuthorize) checks permissions before a method runs.

Each is "advice" applied by a proxy - the same mechanism as the timing aspect. Once you see AOP, you see it all over Spring.

Explain the silent transaction

A teammate reports that @Transactional "isn't working": a method annotated with it runs, but no transaction seems to start. On inspection, that method is being called by another method in the same class. Using what you learned about proxies, explain why the transaction never begins - and suggest a fix.

How does Spring apply an aspect's advice to a bean's methods?

Key takeaways

  • AOP factors out cross-cutting concerns (logging, timing, security, transactions) so you write them once instead of scattering them across many methods.
  • Key terms: aspect (the concern), advice (the code), join point (where it could run), pointcut (which join points to select).
  • Spring implements AOP with proxies - it hands out a wrapped bean that runs advice then delegates to the real object.
  • Self-invocation (this.method()) bypasses the proxy, so advice and @Transactional won't fire on internal calls.
  • You'll mostly consume AOP through @Transactional, @Cacheable, @Async, and method security rather than writing aspects yourself.
War diese Lektion hilfreich?
Diese Seite auf GitHub bearbeiten