⌂ Index
Kapitel 01 · Core

Spring Framework Core: IoC, DI, Beans, Events und AOP

Typ: FrameworkVersion 2 ausführlich

Das Spring Framework liefert den Container, Bean-Lifecycle, Dependency Injection, Events, Ressourcenabstraktion, AOP, Transaktionen, Web- und Data-Integration.

Fachliche Einordnung

Core Spring bestimmt, wie Objekte erzeugt, verbunden, erweitert und getestet werden. Wer Core versteht, versteht auch Boot, Security, Data und Cloud leichter.

Enterprise-Merksatz: Das Spring Framework liefert den Container, Bean-Lifecycle, Dependency Injection, Events, Ressourcenabstraktion, AOP, Transaktionen, Web- und Data-Integration.

Technische Darstellung

ApplicationContext BeanFactory Service Bean Proxy Aspect Repository
Kernkonzepte
  • ApplicationContext als zentrale Laufzeitumgebung.
  • Bean Definition, Scope, Lifecycle Callback und Proxy.
  • Constructor Injection als bevorzugte Form stabiler Abhängigkeiten.
  • AOP für Querschnittsthemen wie Transaktionen, Security, Logging und Observability.
  • Application Events für lose Kopplung innerhalb eines Prozesses.
Wann einsetzen?
  • Du willst testbare Services ohne harte new-Abhängigkeiten bauen.
  • Du willst technische Aspekte von Fachlogik trennen.
  • Du willst verstehen, warum @Transactional, @Cacheable oder @PreAuthorize oft über Proxies wirken.
Typische Fehler und Risiken
  • Field Injection versteckt Pflichtabhängigkeiten und erschwert Tests.
  • Self-invocation umgeht Spring-Proxies und damit @Transactional oder @Async.
  • Zu viel AOP macht Kontrollfluss unsichtbar.
Legacy- und Modernisierungssicht

Aus EJB @Stateless Services werden Spring @Service Beans; Interceptors werden meist zu AOP-Aspekten, Filterketten oder Security-Konfigurationen.

Ausführliches Beispiel

Das Beispiel zeigt bewusst nicht nur Annotationen, sondern auch die Verantwortung der Schicht. In echten Projekten sollte der technische Spring-Code an Adapter- oder Konfigurationsrändern bleiben, während die Fachlogik testbar und möglichst frameworkarm bleibt.

@Service
public class InvoiceService {
    private final InvoiceRepository repository;
    private final ApplicationEventPublisher events;

    public InvoiceService(InvoiceRepository repository, ApplicationEventPublisher events) {
        this.repository = repository;
        this.events = events;
    }

    @Transactional // Proxy Pattern: Spring legt einen Transaktions-Proxy um diese Bean.
    public InvoiceId createInvoice(CreateInvoiceCommand command) {
        Invoice invoice = Invoice.create(command.customerId(), command.lines());
        repository.save(invoice);
        events.publishEvent(new InvoiceCreated(invoice.id()));
        return invoice.id();
    }
}

@Aspect
@Component
class AuditAspect {
    @Around("@annotation(org.springframework.transaction.annotation.Transactional)")
    Object auditTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
        long started = System.nanoTime();
        try { return joinPoint.proceed(); }
        finally { System.out.println("tx method took " + (System.nanoTime() - started)); }
    }
}
Checkliste für Reviews
  • Ist die Verantwortung des Bausteins klar: Framework steuert Lebenszyklus, Library wird gezielt benutzt?
  • Ist die Fachlogik außerhalb von Controller, Listener, Repository-Implementierung oder Konfiguration?
  • Sind Fehlerfälle, Timeouts, Security, Monitoring und Tests sichtbar modelliert?
  • Gibt es klare Grenzen zwischen DTO, Domäne, Persistence und Infrastruktur?