Java-Caching mit Spring
Alexander Stasiak
10. Feb. 2026・12 Min. Lesezeit
Inhaltsverzeichnis
Caching in Java‑Anwendungen verstehen
Erste Schritte: Caching in einem Spring Boot‑Projekt aktivieren
Spring Boot Starter Cache verwenden
Spring Core Caching ohne Spring Boot verwenden
Spring‑Caching aktivieren und konfigurieren
Cache‑Namen und ‑Regionen definieren
Caching mit Spring‑Annotationen verwenden
@Cacheable: Methodenergebnisse cachen
@CacheEvict: Veraltete Einträge entfernen
@CachePut: Cache‑Updates erzwingen
@Caching: Mehrere Cache‑Operationen kombinieren
@CacheConfig: Cache‑Einstellungen zentralisieren
Bedingtes Caching und fortgeschrittene Key‑Strategien
Das Attribut condition verwenden
Das Attribut unless verwenden
Java‑basierte Cache‑Konfigurationen integrieren
In‑Memory‑Cache konfigurieren (z. B. Caffeine)
Verteilten Cache konfigurieren (z. B. Redis)
Best Practices, Fallstricke und Fazit
Wenn Ihre Spring Boot-Anwendung wiederholt dieselben Daten aus einer Datenbank oder einem externen API abruft, verschwenden Sie vermutlich Millisekunden – oder sogar Sekunden – bei jeder Anfrage. Java-Caching mit Spring löst das, indem häufig benötigte Ergebnisse im schnellen Speicher abgelegt werden, sodass nachfolgende Aufrufe den teuren Vorgang vollständig überspringen.
Die Cache-Abstraktion von Spring, eingeführt in Spring Framework 3.1 um 2011 und mit Spring Boot 1.0 in 2014 deutlich verfeinert, bietet einen deklarativen, annotationsgetriebenen Ansatz für Caching. Der große Vorteil: Sie entkoppelt Ihre Geschäftslogik vom zugrunde liegenden Cache-Provider. Ob Sie für die Entwicklung einen einfachen In‑Memory‑Cache nutzen oder in der Produktion Redis einsetzen – Ihr Service-Code bleibt unverändert.
Diese Anleitung zeigt, wie Sie Caching in einem modernen Spring Boot 3 / Java 17-Projekt aktivieren, konfigurieren und nutzen. Das nehmen Sie mit:
- Bessere Performance: Reduzieren Sie Antwortzeiten von hunderten Millisekunden auf unter 1 ms für gecachte Operationen
- Einfacheres Cache-Management: Caching per Annotation statt Boilerplate-Logik
- Leichtere Provider-Migration: Wechseln Sie zwischen ConcurrentMap, Caffeine, Redis oder Ehcache ohne Änderungen an der Geschäftslogik
- Produktionsreife Muster: Lernen Sie Conditional Caching, Cache Eviction und Multi-Cache-Strategien
Caching in Java‑Anwendungen verstehen
Caching speichert häufig verwendete Daten in schnellem Speicher – typischerweise RAM –, um wiederholte, teure Operationen zu vermeiden. In Java-Backends bedeutet das, Methodenaufrufe abzufangen und bereits berechnete Ergebnisse zurückzugeben, statt dieselbe Logik immer wieder auszuführen.
Konkrete Szenarien, in denen Caching glänzt:
- Produktdetails via JPA: Ein E‑Commerce‑Service ruft productRepository.findById(productId) für populäre Artikel tausendfach pro Stunde auf
- User-Profildaten aus einem externen REST API: Jeder Lookup dauert wegen Latenz 150–300 ms
- Konfigurationswerte aus einem Remote‑Service: Feature Flags und Settings, die selten wechseln, aber bei jedem Seitenaufruf benötigt werden
Die Performance-Auswirkung ist erheblich. Ein Datenbankaufruf benötigt meist 200–300 ms (Connection-Overhead, Query-Ausführung, Mapping). Ein Cache-Lookup ist in unter 1 ms erledigt. Bei einem stark frequentierten Endpoint mit 10.000 Requests pro Stunde summiert sich der Unterschied täglich zu Stunden an gesparter Rechenzeit.
Caching adressiert typische Probleme:
- Hohe Latenz bei wiederholten Reads derselben Daten
- Datenbank-Engpässe unter Last, wenn viele Requests identische Queries ausführen
- Drosselung bei Drittanbieter-APIs mit Rate Limits
- Überflüssige Compute-Zyklen für deterministische Berechnungen
Die Cache-Abstraktion von Spring zielt speziell auf Methodenergebnisse. Das ist etwas anderes als HTTP‑Caching oder CDN‑Caching, das von einem Content Delivery Network übernommen wird. Diese Ebenen cachen Antworten näher am Client, während Spring‑Caching in der Service-Schicht Ihrer Web‑Anwendung arbeitet.
Erste Schritte: Caching in einem Spring Boot‑Projekt aktivieren
Dieser Abschnitt zeigt, wie Sie aus einer „plain“ Spring Boot 3‑Anwendung – erstellt mit Spring Initializr in 2025 – in wenigen Minuten eine Anwendung mit Basis‑Caching machen.
Stellen Sie sicher, dass Ihr Projekt nutzt:
- Java 17 oder höher
- Spring Boot 3.x
- Maven (pom.xml) oder Gradle (build.gradle.kts) als Build-Tool
Die Abhängigkeit spring-boot-starter-cache muss hinzugefügt werden. Dieser Starter bringt das Modul spring-context-support und alles Notwendige für die Caching-Infrastruktur mit. Für ein einfaches Demo funktioniert der standardmäßige ConcurrentMapCacheManager ohne weitere Provider-Abhängigkeit.
Der Kernschritt ist, @EnableCaching in Ihrer Spring Boot‑Main-Klasse oder einer dedizierten Konfiguration zu ergänzen. So sieht das aus:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class BookstoreApplication {
public static void main(String[] args) {
SpringApplication.run(BookstoreApplication.class, args);
}
}Mit diesen beiden Bausteinen – der Abhängigkeit und der Annotation – ist Caching einsatzbereit.
Spring Boot Starter Cache verwenden
Das Hinzufügen von spring-boot-starter-cache aktiviert die Auto-Konfiguration der Caching-Infrastruktur. Das ist für die meisten Projekte der empfohlene Weg.
Fügen Sie diese Abhängigkeit zu Ihrer pom.xml hinzu:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>Für Gradle fügen Sie implementation 'org.springframework.boot:spring-boot-starter-cache' im dependencies-Block hinzu.
Das leistet die Auto-Konfiguration:
- Registriert einen Default-CacheManager basierend auf dem, was auf dem Classpath verfügbar ist
- Scannt nach Caching-Annotationen, sobald @EnableCaching vorhanden ist
- Verdrahtet Caches anhand der in application.yml oder application.properties definierten Properties
- Stellt sinnvolle Defaults bereit, die sofort funktionieren
Dieser Starter ist der gleiche Einstiegspunkt – egal, ob Ihr finaler Cache-Provider Caffeine, Redis oder eine einfache In‑Memory‑Map ist. Der einzige Unterschied sind die zusätzlichen Abhängigkeiten, die Sie einbinden.
Spring Core Caching ohne Spring Boot verwenden
Caching funktioniert auch in „plain“ Spring‑Anwendungen – z. B. Spring Framework 6.x ohne Boot. In diesem Fall fügen Sie spring-context und das Modul spring-context-support manuell hinzu.
Ohne Boot‑Auto‑Konfiguration müssen Sie einen CacheManager‑Bean explizit in einer Konfiguration definieren:
- Erstellen Sie eine Java‑Config‑Klasse mit @EnableCaching
- Fügen Sie eine @Bean‑Methode hinzu, die Ihre gewünschte CacheManager‑Implementierung zurückgibt
- Beispiel: return new ConcurrentMapCacheManager("books", "users") mit vordefinierten Cache‑Namen
- Optional konfigurieren Sie einen ausgefeilteren Manager wie CaffeineCacheManager
Dieser Ansatz ist üblich in Legacy‑Java‑EE‑Deployments, eigenständigen Spring‑Bibliotheken oder wenn die Meinungen von Spring Boot nicht zu Ihren Anforderungen passen.
Spring‑Caching aktivieren und konfigurieren
Sobald die Abhängigkeiten stehen, aktivieren Sie das Caching-Verhalten und legen fest, wie Ihr CacheManager arbeiten soll.
Die Annotation @EnableCaching triggert einen Post‑Processor, der Spring‑Beans nach Caching‑Annotationen scannt und Proxys darum legt. Diese Proxys fangen Methodenaufrufe ab, um vor der Ausführung nach gecachten Ergebnissen zu prüfen.
Spring Boot wählt die Standardkonfiguration für den CacheManager per Classpath‑Erkennung:
| Provider auf dem Classpath | Verwendeter CacheManager |
|---|---|
| Keiner (nur Starter) | ConcurrentMapCacheManager |
| Caffeine | CaffeineCacheManager |
| Redis (spring-boot-starter-data-redis) | RedisCacheManager |
| EhCache | EhCacheCacheManager |
Für den Produktivbetrieb empfiehlt sich eine explizite Konfiguration. Definieren Sie einen CaffeineCacheManager oder RedisCacheManager‑Bean, um zu steuern:
- Time‑to‑Live (TTL) für Cache‑Einträge
- Maximale Größe vor Eviction
- Eviction‑Strategien (LRU, LFU, größenbasiert)
- Pro‑Cache‑Konfigurationen mit unterschiedlichen Policies
Spring stellt außerdem CacheManagerCustomizer<T extends CacheManager> als Hook bereit, um von Auto‑Konfiguration erzeugte Caches feinzujustieren, ohne sie komplett zu ersetzen.
Cache‑Namen und ‑Regionen definieren
Caches sind in Spring nach logischen Namen gruppiert – Strings wie „products“, „users“ oder „exchangeRates“. Diese Namen mappen auf Regionen/Räume beim zugrunde liegenden Provider.
Best Practices für die Benennung:
- Wählen Sie aussagekräftige Namen, die die Daten widerspiegeln (z. B. „productById“ statt „cache1“)
- Halten Sie Namen in Annotationen und Konfigurationsdateien konsistent
- Verwenden Sie konsequent Singular oder Plural
- Erwägen Sie in größeren Systemen Präfixe mit Servicenamen („catalog-products“, „pricing-rates“)
Beispiel für eine ProductService‑Klasse:
- „productById“-Cache für Einzelabrufe per ID
- „allProducts“-Cache für Listing‑Endpoints, die Collections zurückgeben
- „productSearch“-Cache für Suchergebnisse mit Query‑Parametern als Keys
Einige Provider wie Redis und Ehcache erlauben pro Region eigene Konfigurationen in einer XML‑Datei oder application.yml, etwa unterschiedliche TTLs und Größen je Cache‑Name.
Caching mit Spring‑Annotationen verwenden
Die Methoden‑Annotationen sind der Hauptweg, um Daten in Ihren Services zu cachen. Das Framework stellt alle nötigen Caching‑Annotationen bereit:
| Annotation | Zweck |
|---|---|
| @Cacheable | Methodenergebnisse cachen; Ausführung bei Cache‑Treffer überspringen |
| @CachePut | Methode immer ausführen; Cache mit Resultat aktualisieren |
| @CacheEvict | Einträge aus dem Cache entfernen |
| @Caching | Mehrere Caching‑Annotationen auf einer Methode kombinieren |
| @CacheConfig | Gemeinsame Cache‑Einstellungen auf Klassenebene setzen |
Diese Annotationen sitzen auf öffentlichen Methoden von Spring‑Beans – typischerweise Klassen mit @Service oder @Repository. Die beim Aktivieren des Cachings erzeugten Proxys fangen Aufrufe ab und setzen das Caching‑Verhalten um.
Standardmäßig bilden die Methodenparameter den Cache‑Schlüssel. Für eine Methode getBook(String isbn) wird die ISBN zum Key. Sie können das mit der Spring Expression Language (SpEL) überschreiben.
Das folgende Beispiel demonstriert die Annotationen in einem BookService.
@Cacheable: Methodenergebnisse cachen
@Cacheable ist für Lese‑Operationen gedacht, deren Rückgabewert wiederverwendbar ist. Denken Sie an findById, getDetails oder Lookup‑Methoden, die bei gleichen Parametern dasselbe Ergebnis liefern.
@Service
public class BookService {
private final BookRepository bookRepository;
@Cacheable(cacheNames = "books", key = "#isbn")
public Book getBookByIsbn(String isbn) {
// This method body only executes on cache miss
simulateSlowService();
return bookRepository.findByIsbn(isbn);
}
private void simulateSlowService() {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}So funktioniert es:
- Erster Aufruf mit ISBN „978-0134685991“: Cache‑Miss → Methode läuft → Ergebnis wird im „books“-Cache gespeichert
- Zweiter Aufruf mit derselben ISBN: Cache‑Hit → Methodenrumpf wird übersprungen → gecachtes Ergebnis kommt sofort zurück
- Aufruf mit anderer ISBN: Cache‑Miss für diesen Key → Methode läuft erneut
Die Annotation prüft vor der Ausführung den Cache. Existiert ein Eintrag für den Key, werden der zugrunde liegende Datenbankzugriff oder die Berechnung vollständig vermieden.
Wann @Cacheable einsetzen:
- Katalogdaten, die sich selten ändern
- Benutzereinstellungen und Präferenzen
- Referenzdaten wie Länder, Währungen oder Kategorien
Wann @Cacheable vermeiden:
- Schreiblastige Methoden, die Zustand ändern
- Methoden mit Nebeneffekten über die Rückgabe hinaus
- Echtzeitdaten, die stets frisch sein müssen
@CacheEvict: Veraltete Einträge entfernen
@CacheEvict invalidiert Cache‑Einträge, wenn sich zugrunde liegende Daten ändern. Nutzen Sie es bei Update‑ oder Delete‑Methoden, um veraltete Daten zu vermeiden.
@CacheEvict(cacheNames = "books", key = "#isbn")
public void updateBookPrice(String isbn, BigDecimal price) {
bookRepository.updatePrice(isbn, price);
}Nach der Ausführung entfernt der Cache den Eintrag zur entsprechenden ISBN. Der nächste Read greift auf die Datenbank zu und cached frische Werte.
Für Bulk‑Operationen – etwa nächtliche Syncs oder Importe – den gesamten Cache leeren:
@CacheEvict(cacheNames = "books", allEntries = true)
public void refreshAllBooks() {
// Bulk import logic
bookRepository.syncFromExternalCatalog();
}Die Option beforeInvocation steuert das Timing:
- beforeInvocation = false (Default): Eviction erfolgt nach erfolgreicher Ausführung
- beforeInvocation = true: Eviction erfolgt davor, also auch bei Exceptions
Paaren Sie Datenänderungen immer mit passender Cache‑Invalidierung. Vergessene Evictions sind eine der häufigsten Ursachen für veraltete Daten in gecachten Anwendungen.
@CachePut: Cache‑Updates erzwingen
@CachePut führt die Methode immer aus und aktualisiert den Cache mit dem Rückgabewert. Ideal für Schreib‑Operationen, die den Cache ohne ausgelassene Logik auffrischen sollen.
@CachePut(cacheNames = "books", key = "#result.isbn")
public Book saveBook(Book book) {
return bookRepository.save(book);
}Beachten Sie den Key #result.isbn – er referenziert den Rückgabewert, also die gespeicherte Entität mit befüllten Feldern.
Zentrale Unterschiede zu @Cacheable:
| Aspekt | @Cacheable | @CachePut |
|---|---|---|
| Methodenausführung | Bei Cache‑Hit übersprungen | Wird immer ausgeführt |
| Cache‑Aktualisierung | Nur bei Cache‑Miss | Immer aktualisiert |
| Typischer Anwendungsfall | Leseoperationen | Schreiboperationen |
Vermeiden Sie es, @Cacheable und @CachePut auf derselben Methode zu kombinieren. Die widersprüchlichen Verhaltensweisen führen zu Verwirrung. Trennen Sie stattdessen Lese‑ und Schreibmethoden klar.
Nutzen Sie @CachePut, wenn Sie:
- den Cache nach Saves/Updates warm halten möchten
- einen nachfolgenden Cache‑Miss nach einem Write vermeiden wollen
- sicherstellen möchten, dass der Cache nach Mutationen den neuesten Stand widerspiegelt
@Caching: Mehrere Cache‑Operationen kombinieren
Java erlaubt nicht, dieselbe Annotation mehrfach auf einer Methode zu deklarieren. @Caching gruppiert mehrere Caching‑Annotationen.
@Caching(
evict = {
@CacheEvict(cacheNames = "books", key = "#book.isbn"),
@CacheEvict(cacheNames = "bestsellers", allEntries = true)
},
put = {
@CachePut(cacheNames = "books", key = "#result.isbn")
}
)
public Book updateBookAndRefreshCaches(Book book) {
return bookRepository.save(book);
}Diese Methode:
- löscht das spezifische Buch aus dem „books“-Cache
- leert den gesamten „bestsellers“-Cache (da sich Rankings ändern können)
- legt das aktualisierte Buch frisch im „books“-Cache ab
Typische Szenarien für @Caching:
- Ein einzelnes Update betrifft mehrere Cache‑Regionen
- Sie brauchen mehrere Annotationen desselben Typs (z. B. Eviction aus drei Caches)
- Komplexe Workflows, in denen Eviction und Refresh zusammen passieren
Trotz der Flexibilität kann starker Einsatz von @Caching die Lesbarkeit mindern. Setzen Sie es für komplexe, gut dokumentierte Fälle ein und kommentieren Sie, warum mehrere Cache‑Operationen nötig sind.
@CacheConfig: Cache‑Einstellungen zentralisieren
@CacheConfig auf Klassenebene definiert gemeinsame Attribute, sodass Sie sie nicht in jeder Methode wiederholen. Das reduziert Duplikate in Services, die denselben Cache in vielen Methoden nutzen.
@Service
@CacheConfig(cacheNames = "books")
public class BookService {
@Cacheable(key = "#isbn")
public Book getBookByIsbn(String isbn) {
return bookRepository.findByIsbn(isbn);
}
@CacheEvict(key = "#isbn")
public void deleteBook(String isbn) {
bookRepository.deleteByIsbn(isbn);
}
@CachePut(key = "#result.isbn")
public Book saveBook(Book book) {
return bookRepository.save(book);
}
}Mit @CacheConfig(cacheNames = "books") auf Klassenebene müssen einzelne Methoden nur noch den Key angeben. Der Cache‑Name wird geerbt.
Sie können außerdem konfigurieren:
- keyGenerator: Den Namen eines benutzerdefinierten Key‑Generators für alle Methoden
- cacheResolver: Einen Custom Cache Resolver zur dynamischen Cache‑Auswahl
- cacheManager: Einen spezifischen CacheManager‑Bean, falls Sie mehrere Manager/Provider parallel nutzen
@CacheConfig aktiviert Caching nicht von selbst. Sie benötigen weiterhin @EnableCaching auf Konfigurationsebene, und einzelne Methoden brauchen ihre @Cacheable-, @CachePut- oder @CacheEvict‑Annotationen.
Bedingtes Caching und fortgeschrittene Key‑Strategien
Nicht jeder Methodenaufruf sollte gecacht werden. Manchmal ist Caching nur für bestimmte Inputs sinnvoll oder wenn das Ergebnis bestimmte Kriterien erfüllt. Spring bietet dafür konditionale Attribute.
Alle relevanten Caching‑Annotationen unterstützen zwei SpEL‑basierte Attribute:
| Attribut | Ausführungszeitpunkt | Zweck |
|---|---|---|
| condition | Vor der Methodenausführung | Entscheidet, ob Caching überhaupt greifen soll |
| unless | Nach der Methodenausführung | Entscheidet, ob das Ergebnis gecacht wird |
Das ist wichtig in Szenarien wie:
- Nur teure Lookups für gültige, wohlgeformte IDs cachen
- Cache für anonyme oder Test‑User überspringen
- Cache‑Verschmutzung mit null‑Ergebnissen oder Fehlerzuständen vermeiden
Auch das Key‑Design verdient Beachtung. Default‑Keys auf Basis aller Parameter reichen für einfache Fälle. Komplexere Methoden profitieren von expliziten Keys, die Kollisionen vermeiden und mit Nullwerten robust umgehen.
Das Attribut condition verwenden
condition wird vor der Ausführung ausgewertet und entscheidet, ob Caching überhaupt berücksichtigt wird. Ergibt die Bedingung false, läuft die Methode ohne Cache‑Interaktion.
@Cacheable(
cacheNames = "books",
key = "#isbn",
condition = "#isbn != null and #isbn.length() == 13"
)
public Book getBookByIsbn(String isbn) {
return bookRepository.findByIsbn(isbn);
}Hier werden nur gültige 13‑stellige ISBNs gecacht. Fehlerhafte oder null‑ISBNs umgehen das Caching vollständig – kein Lookup, keine Speicherung.
Ein weiteres Beispiel basierend auf dem Kundenstatus:
@Cacheable(
cacheNames = "pricing",
key = "#productId",
condition = "#customer.status == 'PREMIUM'"
)
public PricingDetails getPremiumPricing(Long productId, Customer customer) {
return pricingService.calculatePremiumPrice(productId, customer);
}condition funktioniert auch mit @CacheEvict und @CachePut. In einem Multi‑Tenant‑System könnten Sie z. B. nur für bestimmte Tenants evicten:
@CacheEvict(
cacheNames = "tenantData",
key = "#tenantId",
condition = "#tenantId != 'system'"
)
public void updateTenantData(String tenantId, TenantConfig config) {
// Update logic
}Das Attribut unless verwenden
unless wird nach der Ausführung ausgewertet und kann via #result auf den Rückgabewert zugreifen. So lassen sich Entscheidungen treffen wie „nur cachen, wenn das Ergebnis nicht null ist oder eine bestimmte Größe hat“.
@Cacheable(
cacheNames = "books",
key = "#isbn",
unless = "#result == null"
)
public Book getBookByIsbn(String isbn) {
return bookRepository.findByIsbn(isbn);
}So verhindern Sie das Cachen fehlender Datensätze. Ohne diese Klausel würde eine nicht gefundene ISBN null cachen – spätere Anfragen blieben null, selbst wenn das Buch später hinzugefügt wird.
Ein weiteres Beispiel abhängig von der Ergebnisgröße:
@Cacheable(
cacheNames = "searchResults",
key = "#query",
unless = "#result.size() > 1000 or #result.isEmpty()"
)
public List<Book> searchBooks(String query) {
return bookRepository.search(query);
}Das vermeidet das Cachen von:
- Leeren Ergebnissen (die ggf. nur „noch keine Treffer“ bedeuten)
- Sehr großen Ergebnissen, die zu viel Cache‑Speicher fressen
condition und unless lassen sich kombinieren:
- condition: „Soll Caching überhaupt versucht werden?“ (vor der Ausführung)
- unless: „Angesichts dieses Ergebnisses: Sollen wir speichern?“ (nach der Ausführung)
Java‑basierte Cache‑Konfigurationen integrieren
Auch wenn Spring Boot vieles auto‑konfiguriert, geben Java‑Konfigurationen Ihnen präzise Kontrolle über Policies wie TTL, maximale Größe und Eviction‑Verhalten.
Das gängige Muster: Eine Konfigurationsklasse mit @Bean‑Methoden, die konfigurierte CacheManager‑Instanzen zurückgeben:
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager manager = new CaffeineCacheManager();
manager.setCaffeine(Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(Duration.ofMinutes(10))
.recordStats());
return manager;
}
}Mit Java‑Config können Sie pro Cache unterschiedliche Policies definieren. Beispiel:
- „customers“-Cache mit 10‑Minuten‑TTL für häufig wechselnde Daten
- „countries“-Cache mit 24‑Stunden‑TTL für Referenzdaten
- „exchangeRates“-Cache mit 5‑Minuten‑TTL für externe API‑Ergebnisse
Der CacheManager verbindet Ihre annotierten Service‑Methoden mit dem tatsächlichen Speicher. Ein CustomerDataService mit @Cacheable("customers") nutzt die für diesen Cache‑Namen definierten Settings.
In‑Memory‑Cache konfigurieren (z. B. Caffeine)
Caffeine ist ein performanter lokaler Cache für Spring‑Anwendungen, die in einer einzelnen JVM laufen. Empfohlen, wenn Sie kein verteiltes Caching über mehrere Instanzen benötigen.
Fügen Sie die Caffeine‑Abhängigkeit hinzu:
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>Konfigurieren Sie den CaffeineCacheManager mit Policies:
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager manager = new CaffeineCacheManager("products", "categories");
manager.setCaffeine(Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(Duration.ofMinutes(5))
.recordStats());
return manager;
}Diese Konfiguration:
- erstellt benannte Caches für „products“ und „categories“
- limitiert jeden Cache auf maximal 10.000 Einträge (verhindert unnötigen Speicherverbrauch)
- lässt Einträge 5 Minuten nach dem Schreiben ablaufen
- erfasst Hit/Miss‑Statistiken fürs Monitoring
Für eine einfache Einrichtung bietet Spring Boot eine direkte Integration über application.yml:
spring:
cache:
type: caffeine
caffeine:
spec: maximumSize=10000,expireAfterWrite=5mCaffeine eignet sich besonders für:
- Single‑Node‑Deployments oder kleine Cluster
- Niedrigste Latenzanforderungen (Sub‑Mikrosekunden‑Lookups)
- Leseintensive Workloads mit 95%+ Hit‑Rates
Verteilten Cache konfigurieren (z. B. Redis)
Redis ist in der Produktion weit verbreitet als verteilter In‑Memory‑Datenspeicher. Es ist die erste Wahl für Caching in Microservices oder skalierten Spring Boot‑Deployments, in denen mehrere Instanzen Daten teilen müssen.
Fügen Sie Spring Data Redis hinzu:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>Konfigurieren Sie die Verbindung in application.yml:
spring:
redis:
host: localhost
port: 6379
password: ${REDIS_PASSWORD:}
cache:
type: redis
redis:
time-to-live: 600sSpring Boot auto‑konfiguriert den RedisCacheManager – oder Sie definieren Ihren eigenen Bean für pro‑Cache‑Konfigurationen:
@Bean
public RedisCacheManagerBuilderCustomizer cacheManagerCustomizer() {
return builder -> builder
.withCacheConfiguration("shortLived",
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(1)))
.withCacheConfiguration("longLived",
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(24)));
}Konkrete Einsatzszenarien für Redis‑Caching:
- Authentifizierungstokens, die zwischen Instanzen hinter einem Load Balancer geteilt werden
- Sitzungsähnliche Daten in stateless Deployments
- API‑Response‑Caching für zukünftige Anfragen im gesamten Cluster
- Feature Flags und Konfigurationen, die über Knoten hinweg konsistent sein müssen
Abwägungen:
- Netzwerklatenz addiert 5–10 ms gegenüber In‑Process‑Caffeine
- Erfordert Serialisierung (typisch JSON via Jackson), was Overhead bedeutet
- Bessere Skalierbarkeit und geteilte Zustände zwischen Services
- Redis bewältigt 100k+ Operationen pro Sekunde pro Shard

Best Practices, Fallstricke und Fazit
Sie haben nun die Grundlagen von Spring Boot‑Caching kennengelernt: die Cache‑Abstraktion aktivieren, @Cacheable/@CachePut/@CacheEvict und andere Annotationen einsetzen, bedingtes Caching anwenden und Provider‑Optionen wie Caffeine und Redis konfigurieren.
Beachten Sie diese Best Practices:
- Angemessene TTLs wählen: Frische und Performance ausbalancieren. Zu kurz bedeutet ständige Misses, zu lang birgt Stale‑Risiken
- Hochvolatile Daten nicht cachen: Wenn sich Daten sekündlich ändern, bringt Caching mehr Komplexität als Nutzen
- Klar benennen: Deskriptive, konsistente Cache‑Namen, die die Domänenobjekte widerspiegeln
- Writes mit Invalidation paaren: Jede mutierende Methode sollte relevante Caches evicten oder aktualisieren
- Hit/Miss‑Metriken monitoren: Nutzen Sie das Spring Boot Actuator‑Endpoint /actuator/caches zur Erfolgskontrolle
Häufige Fallstricke, die Sie vermeiden sollten:
| Fallstrick | Problem | Lösung |
|---|---|---|
| Selbstaufruf | Ein gecachter Methodenaufruf aus derselben Klasse umgeht den Proxy | Über die injizierte Bean aufrufen oder in separate Klassen refaktorieren |
| Eviction vergessen | Writes passieren, aber der Cache liefert alte Daten | @CacheEvict zu allen Mutationsmethoden hinzufügen |
| Unbegrenzte Caches | Speicherauslastung wächst bis zum OOM | Immer maximumSize oder Eintragslimits setzen |
| nulls cachen | Fehlende Datensätze werden unbegrenzt gehalten | unless = "#result == null" verwenden |
| Over‑Caching | Jede beliebige Methode bekommt @Cacheable | Selektiv cachen, wo Latenz zählt |
Überzeugen Sie sich selbst mit dieser Übung:
- Erstellen Sie einen einfachen Endpoint wie /api/books/{isbn}, der eine langsame Servicemethode aufruft
- Fügen Sie der Servicemethode @Cacheable hinzu
- Messen Sie die Antwortzeiten vorher/nachher mit Spring Boot Actuator‑Metriken oder einem Tool wie JMeter
- Beobachten Sie die Logs – die Methode läuft nur bei Cache‑Misses
Die Cache‑Abstraktion von Spring bietet eine konsistente, annotationsgetriebene Schicht, die providerübergreifend funktioniert. Sie können in der Entwicklung mit einem einfachen In‑Memory‑Cache starten, im Single‑Node‑Betrieb Caffeine nutzen und beim Skalieren auf mehrere Instanzen zu Redis wechseln – ohne Änderungen am Service‑Code.
Mehr dazu finden Sie in der offiziellen Dokumentation zu Spring Boot Caching sowie in erweiterten Mustern wie Cache‑Aside mit reaktiver Unterstützung in neueren Spring Boot 3.x‑Releases.
Die populärsten Frameworks sind nicht zufällig beliebt – das Caching von Spring ist erprobt, flexibel und bereit für jede Skalierung, die Ihre Anwendung verlangt. Starten Sie klein, messen Sie den Effekt und erweitern Sie Ihre Caching‑Strategie mit wachsenden Performance‑Anforderungen.
Digital Transformation Strategy for Siemens Finance
Cloud-based platform for Siemens Financial Services in Poland


Bereit, Ihr Know-how mit KI zu zentralisieren?
Beginnen Sie ein neues Kapitel im Wissensmanagement – wo der KI-Assistent zum zentralen Pfeiler Ihrer digitalen Support-Erfahrung wird.
Kostenlose Beratung buchenArbeiten Sie mit einem Team, dem erstklassige Unternehmen vertrauen.
Wir entwickeln, was als Nächstes kommt.
Dienste





