18 Was passiert beim Projektstart?

Du startest die Anwendung mit ./gradlew bootRun. Zwei Sekunden später läuft sie. Was ist in dieser Zeit passiert? Ein Blick hinter die Kulissen.

18.1 Die Startsequenz

18.2 Phase 1: Bootstrap

Die main-Methode ruft SpringApplication.run() auf:

public static void main(String[] args) {
    SpringApplication.run(ArcadeHighscoreApplication.class, args);
}

Spring Boot initialisiert sich:

In der Konsole siehst du das Banner – ein Zeichen, dass Phase 1 abgeschlossen ist.

18.3 Phase 2: Component Scan

Spring durchsucht die Packages nach Komponenten. Ausgangspunkt ist das Package der Hauptklasse.

Scanning: de.digitalfrontiers.arcade
  Found: ArcadeHighscoreApplication (@SpringBootApplication)
  
Scanning: de.digitalfrontiers.arcade.web
  Found: HomeController (@Controller)
  
Scanning: de.digitalfrontiers.arcade.service
  Found: GameService (@Service)
  
Scanning: de.digitalfrontiers.arcade.repository
  Found: InMemoryGameRepository (@Repository)

Das Ergebnis ist eine Liste von Bean-Definitionen. Noch keine Objekte – nur Baupläne.

18.4 Phase 3: Dependency Resolution

Spring analysiert die Abhängigkeiten. Wer braucht wen?

Spring baut einen Abhängigkeitsgraphen. Daraus ergibt sich die Reihenfolge der Bean-Erzeugung:

  1. InMemoryGameRepository (keine Abhängigkeiten)
  2. GameService (braucht Repository)
  3. HomeController (braucht Service)

Beans ohne Abhängigkeiten zuerst, abhängige Beans danach.

18.5 Phase 4: Bean-Erzeugung

Jetzt entstehen die Objekte. Für jede Bean:

Am Beispiel GameService:

// 1. Spring ruft den Konstruktor
GameService service = new GameService(inMemoryGameRepository);

// 2. Dependencies bereits injiziert (Constructor Injection)

// 3. @PostConstruct aufrufen (falls vorhanden)

// 4. Bean im Container registrieren

Nach dieser Phase existieren alle Beans als fertige, verdrahtete Objekte.

18.6 Phase 5: Auto-Configuration

Parallel zur Bean-Erzeugung arbeitet die Auto-Configuration. Spring Boot prüft den Classpath:

Checking: Tomcat im Classpath?
  -> Ja: EmbeddedTomcatConfiguration aktiviert

Checking: Thymeleaf im Classpath?
  -> Ja: ThymeleafAutoConfiguration aktiviert

Checking: MongoDB im Classpath?
  -> Nein: MongoAutoConfiguration uebersprungen

Für jede erkannte Bibliothek werden zusätzliche Beans erzeugt. Tomcat-Konfiguration, Template-Resolver, JSON-Mapper.

18.7 Phase 6: Server-Start

Der eingebettete Tomcat startet:

Tomcat initialized with port(s): 8080 (http)
Starting service [Tomcat]
Starting Servlet engine: [Apache Tomcat/10.1.x]
Initializing Spring embedded WebApplicationContext
Tomcat started on port(s): 8080 (http)

Die Anwendung ist bereit. HTTP-Requests werden entgegengenommen.

18.8 Die Konsolenausgabe lesen

Spring Boot ist gesprächig. Die Logs erzählen die Geschichte:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \     <- Banner (Phase 1)
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 
INFO  Starting ArcadeHighscoreApplication     <- Bootstrap
INFO  No active profile set, falling back     <- Konfiguration
INFO  Tomcat initialized with port: 8080      <- Server-Init
INFO  Starting service [Tomcat]               <- Server-Start
INFO  Initializing WebApplicationContext      <- Context-Init
INFO  Started ArcadeHighscoreApplication      <- Fertig!
      in 2.1 seconds (process running for 2.5)

Die letzte Zeile zeigt die Startzeit. Unter drei Sekunden ist typisch für kleine Anwendungen.

18.9 Wenn etwas schiefgeht

Fehler in der Startsequenz führen zum Abbruch. Häufige Ursachen:

Bean nicht gefunden

Parameter 0 of constructor in GameService required a bean 
of type 'GameRepository' that could not be found.

→ Klasse nicht annotiert oder im falschen Package.

Zirkuläre Abhängigkeit

The dependencies of some of the beans form a cycle:
  serviceA -> serviceB -> serviceA

→ A braucht B, B braucht A. Architektur überdenken.

Port belegt

Web server failed to start. Port 8080 was already in use.

→ Andere Anwendung läuft. Port ändern oder Prozess beenden.

18.10 Die Startzeit optimieren

Für Entwicklung ist schneller Start wichtig. Tipps:

Maßnahme Effekt
Scan-Bereich begrenzen Weniger Klassen zu prüfen
Lazy Initialization Beans erst bei Bedarf erzeugen
DevTools verwenden Hot-Reload statt Neustart
Unnötige Starter entfernen Weniger Auto-Configuration

Lazy Initialization aktivieren:

spring:
  main:
    lazy-initialization: true

Beans werden erst erzeugt, wenn sie gebraucht werden. Schnellerer Start, aber erste Requests langsamer.

Für Produktion ist Startzeit weniger kritisch. Da zählt Stabilität.