14 Bean Lifecycle im Überblick

Spring verwaltet den gesamten Lebenszyklus einer Bean – von der Geburt bis zum Tod. Für den Einstieg reicht ein grobes Verständnis dieses Prozesses.

14.1 Was ist eine Bean?

Eine Bean ist ein Objekt, das Spring verwaltet. Nicht jedes Objekt in deiner Anwendung ist eine Bean. Nur die, die Spring kennt und kontrolliert.

Die Domain-Klassen Score, Player, Game sind keine Beans. Du erzeugst sie selbst mit new. Die Service-, Repository- und Controller-Klassen sind Beans. Spring erzeugt und verwaltet sie.

14.2 Der Lebenszyklus

Vereinfacht durchläuft jede Bean diese Phasen:

Phase 1 – Klassensuche: Spring scannt Packages nach Klassen mit bestimmten Annotationen (@Component, @Service, etc.).

Phase 2 – Instanziierung: Spring ruft den Konstruktor auf und erzeugt das Objekt.

Phase 3 – Injection: Spring setzt die Abhängigkeiten – per Konstruktor, Setter oder Feld.

Phase 4 – Initialisierung: Methoden mit @PostConstruct werden aufgerufen.

Phase 5 – Zerstörung: Beim Herunterfahren werden Methoden mit @PreDestroy aufgerufen.

14.3 Initialisierung mit @PostConstruct

Manchmal muss eine Bean nach der Injection noch etwas tun. Dafür gibt es @PostConstruct:

@Service
public class GameCatalogService {
    
    private final GameRepository gameRepository;
    private Map<String, Game> gameCache;
    
    public GameCatalogService(GameRepository gameRepository) {
        this.gameRepository = gameRepository;
        // Hier ist gameRepository noch nicht gesetzt bei Field Injection!
    }
    
    @PostConstruct
    public void initialize() {
        // Wird aufgerufen, NACHDEM alle Abhängigkeiten gesetzt sind
        this.gameCache = gameRepository.findAll().stream()
            .collect(Collectors.toMap(Game::getId, g -> g));
        log.info("Game cache initialized with {} games", gameCache.size());
    }
}

Die Reihenfolge ist garantiert:

  1. Konstruktor wird aufgerufen
  2. Abhängigkeiten werden injiziert
  3. @PostConstruct-Methode wird aufgerufen

Im Konstruktor sind bei Field oder Setter Injection die Abhängigkeiten noch null. In @PostConstruct sind sie garantiert gesetzt.

14.4 Aufräumen mit @PreDestroy

Manche Beans halten Ressourcen, die beim Beenden freigegeben werden müssen:

@Service
public class ConnectionPoolService {
    
    private ExecutorService executor;
    
    @PostConstruct
    public void init() {
        executor = Executors.newFixedThreadPool(10);
        log.info("Connection pool started");
    }
    
    @PreDestroy
    public void cleanup() {
        executor.shutdown();
        log.info("Connection pool shut down");
    }
}

Spring ruft @PreDestroy automatisch beim Herunterfahren. Du musst nicht selbst auf Shutdown-Hooks achten.

14.5 Bean Scope: Singleton

Standardmäßig existiert jede Bean genau einmal. Egal wie oft sie injiziert wird – es ist immer dieselbe Instanz.

Drei Controller, eine Service-Instanz. Das ist effizient und in den meisten Fällen das gewünschte Verhalten.

@Service  // Default: Singleton
public class HighscoreService {
    // Diese Instanz wird mit allen Controllern geteilt
}

Es gibt andere Scopes (Prototype, Request, Session), aber für den Einstieg ist Singleton der einzig relevante.

14.6 Was du wissen musst

Für die tägliche Arbeit reicht dieses Wissen:

Konzept Bedeutung
Bean Von Spring verwaltetes Objekt
Singleton Eine Instanz pro Anwendung (Default)
@PostConstruct Wird nach Injection aufgerufen
@PreDestroy Wird vor dem Herunterfahren aufgerufen

Die Details des Lifecycles – BeanPostProcessor, InitializingBean, DisposableBean – sind fortgeschrittene Themen. Sie werden relevant, wenn du eigene Frameworks schreibst oder Spring erweitern willst.

Für Anwendungsentwicklung gilt: Spring kümmert sich. Du definierst die Beans, Spring verwaltet sie. Vertraue dem Container.