Der ApplicationContext ist das Gehirn einer Spring-Anwendung. Er kennt alle Beans, verwaltet ihre Lebenszyklen und vermittelt zwischen ihnen. Wenn du Spring verstehen willst, musst du den ApplicationContext verstehen.
Technisch ist der ApplicationContext ein Interface. Praktisch ist er der Container, der alles zusammenhält.
Die Bean Registry speichert alle Bean-Definitionen. Die Bean Factory erzeugt Beans bei Bedarf. Das Event System ermöglicht Kommunikation zwischen Komponenten. Der Resource Loader findet Dateien und Konfigurationen. Das Environment kennt Properties und Profile.
Im Arcade-Projekt existiert genau ein ApplicationContext. Er wird beim Start erzeugt:
@SpringBootApplication
public class ArcadeHighscoreApplication {
public static void main(String[] args) {
// run() erzeugt und konfiguriert den ApplicationContext
ApplicationContext context = SpringApplication.run(
ArcadeHighscoreApplication.class, args);
}
}Nach dem Start kannst du den Context befragen:
// Alle Bean-Namen ausgeben
String[] beanNames = context.getBeanDefinitionNames();
for (String name : beanNames) {
System.out.println(name);
}
// Eine bestimmte Bean holen
GameService gameService = context.getBean(GameService.class);In der Praxis brauchst du das selten. Spring injiziert Beans automatisch. Aber zu wissen, dass der Context existiert, hilft beim Verständnis.
Der ApplicationContext garantiert: Jede Bean existiert genau einmal.
Egal wie oft du getBean() aufrufst oder wie oft eine Bean
injiziert wird – es ist immer dieselbe Instanz.
Drei Konsumenten, eine Instanz. Das spart Speicher und stellt sicher, dass alle denselben Zustand sehen.
In komplexen Anwendungen kann es mehrere Contexts geben. Ein Parent-Context enthält gemeinsame Beans, Child-Contexts enthalten spezifische.
Für das Arcade-Projekt und die meisten Spring-Boot-Anwendungen ist das irrelevant. Ein Context reicht. Aber das Konzept erklärt, warum manche Dokumentation von “Contexts” im Plural spricht.
Beans kommunizieren nicht direkt miteinander. Sie kommunizieren über den Context.
Wenn der HomeController den GameService
aufruft, weiß er nicht, wo der Service herkommt. Er hat eine Referenz,
die der Context bereitgestellt hat. Diese Indirektion ermöglicht:
Der Context ist der unsichtbare Mittelsmann, der alles orchestriert.
In älteren Tutorials taucht manchmal BeanFactory auf.
Das ist der Vorfahre des ApplicationContext – schlanker, aber mit
weniger Features.
| Feature | BeanFactory | ApplicationContext |
|---|---|---|
| Bean-Erzeugung | Ja | Ja |
| Dependency Injection | Ja | Ja |
| Lifecycle Callbacks | Eingeschränkt | Vollständig |
| Event System | Nein | Ja |
| Internationalisierung | Nein | Ja |
| Resource Loading | Nein | Ja |
ApplicationContext ist die moderne Wahl. BeanFactory ist Legacy. In Spring Boot arbeitest du immer mit ApplicationContext.
Manchmal brauchst du direkten Zugriff auf den Context. Spring bietet
dafür ApplicationContextAware:
@Service
public class DynamicServiceLoader implements ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext context) {
this.context = context;
}
public <T> T getService(Class<T> serviceType) {
return context.getBean(serviceType);
}
}Oder eleganter per Injection:
@Service
public class DynamicServiceLoader {
private final ApplicationContext context;
public DynamicServiceLoader(ApplicationContext context) {
this.context = context;
}
}Der ApplicationContext ist selbst eine Bean. Du kannst ihn injizieren wie jede andere Abhängigkeit.
Aber Vorsicht: Direkter Context-Zugriff ist oft ein Zeichen für
Design-Probleme. Wenn du getBean() rufst, umgehst du die
Dependency Injection. Tu das nur, wenn es wirklich nötig ist – etwa für
dynamisches Laden von Plugins.