26 ApplicationContext

Der ApplicationContext ist das Herzstück des Spring Frameworks und bildet die zentrale Komponente für die Verwaltung und das Management der Beans in einer Spring-Anwendung. Der ApplicationContext stellt eine Erweiterung des einfachen BeanFactory-Containers dar und bietet umfangreiche Funktionen wie Event-Publishing, Bean-Lifecycle-Management, und vieles mehr. In diesem Kapitel gehen wir auf die Funktionsweise des ApplicationContext in Spring Boot ein, erläutern seine Rolle, seine Konfiguration und wie Sie ihn effektiv in Ihren Anwendungen nutzen können.

26.1 Was ist der ApplicationContext?

Der ApplicationContext ist eine Implementierung des Inversion of Control (IoC)-Containers in Spring. Er übernimmt die Instanziierung, Verwaltung und das Wiring der Beans in einer Spring-Anwendung. Während BeanFactory nur grundlegende Funktionen für das Laden und Verwalten von Beans bietet, erweitert der ApplicationContext diese Funktionalitäten, um Dinge wie:

26.1.1 Typen von ApplicationContext

In Spring gibt es verschiedene Implementierungen des ApplicationContext, die je nach Anwendungsfall eingesetzt werden:

In Spring Boot verwenden wir hauptsächlich den AnnotationConfigApplicationContext, da Spring Boot stark auf Annotations basiert.

26.1.2 Grundstruktur und Initialisierung des ApplicationContext

In einer typischen Spring Boot-Anwendung wird der ApplicationContext automatisch beim Start der Anwendung initialisiert. Spring Boot verwendet den SpringApplication-Klassenmechanismus, um den ApplicationContext zu erstellen und zu initialisieren.

Beispiel: Initialisierung des ApplicationContext in einer Spring Boot Anwendung

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

Hier erstellt SpringApplication.run(MyApp.class, args) automatisch den ApplicationContext und initialisiert alle Beans.

26.2 Bean Lifecycle im ApplicationContext

Jede Bean, die vom ApplicationContext verwaltet wird, durchläuft einen festen Lifecycle, der mehrere Phasen umfasst:

  1. Instanziierung: Der ApplicationContext erstellt die Bean-Instanz.
  2. Dependency Injection: Abhängigkeiten der Bean werden aufgelöst und injiziert.
  3. Initialisierung: Wenn vorhanden, werden Methoden wie @PostConstruct oder InitializingBean.afterPropertiesSet() aufgerufen.
  4. Zerstörung: Bei der Bean-Zerstörung werden Methoden wie @PreDestroy oder DisposableBean.destroy() aufgerufen.

26.2.1 Beispiel: Bean Lifecycle in Spring Boot

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;

@Component
public class MyService {

    public MyService() {
        System.out.println("MyService: Konstruktor aufgerufen");
    }

    @PostConstruct
    public void init() {
        System.out.println("MyService: Initialisierung");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("MyService: Vor der Zerstörung");
    }
}

In diesem Beispiel wird die Bean MyService beim Start der Anwendung instanziiert, die Methode init() wird nach der Dependency Injection aufgerufen, und destroy() wird kurz vor der Zerstörung der Bean ausgeführt.

26.3 Zugriff auf den ApplicationContext

Manchmal kann es erforderlich sein, direkt auf den ApplicationContext zuzugreifen, um bestimmte Funktionen zu nutzen, wie das Laden von Beans zur Laufzeit oder das Auslösen von Events.

26.3.1 Zugriff auf den ApplicationContext in einer Bean

Sie können den ApplicationContext über Dependency Injection oder durch Implementieren des ApplicationContextAware-Interfaces erhalten.

Beispiel: Injection des ApplicationContext

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class MyContextAwareBean implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public void printAllBeans() {
        String[] allBeanNames = applicationContext.getBeanDefinitionNames();
        for(String beanName : allBeanNames) {
            System.out.println(beanName);
        }
    }
}

Hier wird der ApplicationContext in der Bean MyContextAwareBean injiziert, wodurch Sie auf alle Beans im Kontext zugreifen können.

26.3.2 Manuelles Abrufen von Beans

Der ApplicationContext ermöglicht es Ihnen, Beans zur Laufzeit zu laden, indem Sie deren Namen oder Typen angeben.

Beispiel: Beans zur Laufzeit abrufen

public class MyBeanRetriever {

    private final ApplicationContext context;

    public MyBeanRetriever(ApplicationContext context) {
        this.context = context;
    }

    public void retrieveBean() {
        MyService myService = context.getBean(MyService.class);
        myService.doSomething();
    }
}

In diesem Beispiel wird die Bean MyService dynamisch aus dem ApplicationContext abgerufen.

26.4 Event Handling im ApplicationContext

Der ApplicationContext unterstützt ein Event-Handling-System, mit dem Sie Ereignisse veröffentlichen und darauf reagieren können. Dies ermöglicht die Implementierung einer Event-getriebenen Architektur.

26.4.1 Senden von Events

Sie können eigene Events definieren, die von anderen Komponenten der Anwendung verarbeitet werden.

Beispiel: Definieren und Senden eines benutzerdefinierten Events

import org.springframework.context.ApplicationEvent;

public class MyCustomEvent extends ApplicationEvent {
    private final String message;

    public MyCustomEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

Beispiel: Senden des Events

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

@Component
public class EventPublisher {

    private final ApplicationEventPublisher eventPublisher;

    public EventPublisher(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    public void publishEvent(String message) {
        MyCustomEvent event = new MyCustomEvent(this, message);
        eventPublisher.publishEvent(event);
    }
}

26.4.2 Empfangen von Events

Andere Komponenten können auf diese Events reagieren, indem sie Event-Listener implementieren.

Beispiel: Event-Listener

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyEventListener {

    @EventListener
    public void handleMyCustomEvent(MyCustomEvent event) {
        System.out.println("Empfangenes Event: " + event.getMessage());
    }
}

In diesem Beispiel veröffentlicht der EventPublisher das MyCustomEvent, und der MyEventListener empfängt das Event und verarbeitet es.

26.5 Best Practices für die Verwendung des ApplicationContext

  1. Vermeiden Sie direkte Abhängigkeiten vom ApplicationContext: Setzen Sie den ApplicationContext sparsam ein. Versuchen Sie, Beans durch Dependency Injection zu verwalten, anstatt direkt auf den ApplicationContext zuzugreifen.

  2. Nutzen Sie Events gezielt: Verwenden Sie das Event-System, um lose gekoppelte Komponenten zu erstellen, die auf Systemereignisse reagieren. Stellen Sie sicher, dass Events nicht für enge Kopplungen zwischen Komponenten genutzt werden.

  3. Laden Sie Beans zur Laufzeit nur wenn nötig: Laden Sie Beans zur Laufzeit aus dem ApplicationContext nur, wenn es unvermeidbar ist. Dies kann die Übersichtlichkeit des Codes verschlechtern.

26.6 tl;dr

Der ApplicationContext ist eine zentrale Komponente im Spring-Framework, die nicht nur das Lifecycle-Management und die Verwaltung von Beans übernimmt, sondern auch Funktionen wie Event-Handling und Internationalisierung unterstützt. In Spring Boot wird der ApplicationContext automatisch initialisiert und verwaltet, wodurch die Konfiguration und Handhabung von Beans erleichtert wird. Durch die Nutzung der Möglichkeiten des ApplicationContext können Sie flexible, erweiterbare und wartbare Anwendungen entwickeln.