Spring Boot 4 – komplett guide · Lektion

Cachning med Spring Cache

Implementera cachningsmekanismer med Spring:s `@Cacheable` och relaterade annotationer för att förbättra svarstiderna.

Lektion 3 av 411 steg

Cachning med Spring Cache är en gratis lektion i Spring Boot 4 – komplett guide på CoddyKit. Detta är lektion 3 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Spring Boot 4 – komplett guide, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Spring Boot 4 – komplett guide innehåller totalt 4 lektioner.

Förbättra prestandan med cachning!

Föreställ er att er app hela tiden hämtar samma data från en långsam databas. Det kan göra den trög! Cachning är som en supersnabb genväg för data som används ofta.

I stället för att gå till databasen varje gång lagrar appen en kopia av datan på en tillfällig plats med snabb åtkomst (cachen). När datan efterfrågas igen kontrollerar appen cachen först.

  • Snabbare svar: Användarna får data snabbare.
  • Minskad belastning: Mindre belastning på databasen eller externa tjänster.

Spring Cache: enkelhet och kraft

Spring Framework erbjuder en fantastisk abstraktion för cachning. Den förenklar integreringen av cachning i era applikationer, så att ni inte behöver skriva komplex cachningslogik själva.

Med Spring Cache kan ni använda enkla annoteringar för att tillämpa cachningsbeteende på era metoder. Det stöder olika underliggande cacheleverantörer som EhCache, Redis och Caffeine, vilket gör att ni enkelt kan byta mellan dem utan att ändra koden.

Kom igång: Lägg till beroenden

För att använda Springs cachningsabstraktion behöver ni lägga till beroendet spring-boot-starter-cache. Detta starter-paket tillhandahåller Springs cachningsinfrastruktur och som standard en enkel cachehanterare med data i minnet.

För en mer robust cache i minnet lägger vi även till Caffeine, ett högpresterande cachningsbibliotek för Java.

pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
</dependency>

Aktivera cachning och @Cacheable

Först behöver ni aktivera cachning i Spring Boot-applikationen genom att lägga till annoteringen @EnableCaching i huvudklassen för applikationen eller i en konfigurationsklass.

Annoteringen @Cacheable används sedan på en metod för att ange att resultatet ska cachas. Första gången metoden anropas lagras resultatet. Efterföljande anrop med samma argument returnerar det cachade resultatet utan att metoden körs.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching // Enable caching for the app
public class CachingApp {
  public static void main(String[] args) {
    SpringApplication.run(CachingApp.class, args);
  }
}

@Cacheable i praktiken: servicelagret

Nu ska vi se @Cacheable på en servicemetod. Observera attributet cacheNames, som anger namnet på cachen där resultaten ska lagras (till exempel "products").

När getProductById anropas kontrollerar Spring cachen "products". Om en produkt med det ID:t hittas returneras den. Annars körs metoden (vilket simulerar ett databasanrop) och resultatet cachas.

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

// Imagine this is a simple data class
class Product {
  private Long id;
  private String name;
  public Product(Long id, String name) {
    this.id = id; this.name = name;
  }
  public Long getId() { return id; }
  public String getName() { return name; }
  @Override
  public String toString() {
    return "Product{" + id + ", " + name + "}";
  }
}

@Service
public class ProductService {
  @Cacheable(cacheNames = "products")
  public Product getProductById(Long id) {
    System.out.println(
      "Fetching product " + id + " from DB...");
    // Simulate a slow database call
    try { Thread.sleep(1000); } 
    catch (InterruptedException e) {}
    return new Product(id, "Product-" + id);
  }
}

// Main Application (from previous scene)
// Add a runner to demonstrate
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;

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

  @Bean
  public CommandLineRunner run(ProductService service) {
    return args -> {
      System.out.println("First call:");
      System.out.println(service.getProductById(1L));

      System.out.println("Second call (cached):");
      System.out.println(service.getProductById(1L));

      System.out.println("Third call (new ID):");
      System.out.println(service.getProductById(2L));
    };
  }
}

Håll cachen uppdaterad med @CachePut

Vad händer om ni uppdaterar en produkt? Den gamla versionen kan fortfarande finnas i cachen! Annoteringen @CachePut används för att uppdatera cachen med resultatet av en metodkörning.

Till skillnad från @Cacheable kör @CachePut alltid metoden och placerar sedan resultatet i cachen. Det passar perfekt för uppdateringsoperationer där ni vill att cachen ska återspegla de senaste uppgifterna.

import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;

// Product and CachingApp classes as before

@Service
public class ProductService {
  // ... getProductById as before ...

  @CachePut(cacheNames = "products", key = "#product.id")
  public Product updateProduct(Product product) {
    System.out.println(
      "Updating product " + product.getId() + " in DB...");
    // Simulate DB update
    try { Thread.sleep(500); } 
    catch (InterruptedException e) {}
    return product; // Return updated product
  }
}

// Main Application
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

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

  @Bean
  public CommandLineRunner run(ProductService service) {
    return args -> {
      System.out.println("--- @CachePut Demo ---");
      Product p1 = service.getProductById(1L); // Cached
      System.out.println("Fetched: " + p1);

      Product updatedP1 = new Product(1L, "Updated Product 1");
      service.updateProduct(updatedP1); // Updates cache
      System.out.println("Updated: " + updatedP1);

      Product p1AfterUpdate = service.getProductById(1L); // Fetches from updated cache
      System.out.println("After update: " + p1AfterUpdate);
    };
  }
}

// Product class (same as before)
class Product {
  private Long id;
  private String name;
  public Product(Long id, String name) {
    this.id = id; this.name = name;
  }
  public Long getId() { return id; }
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
  @Override
  public String toString() {
    return "Product{" + id + ", '" + name + "'}";
  }
}

Rensa cachen med @CacheEvict

När ett objekt tas bort vill ni ta bort det från cachen så att inaktuella data inte råkar skickas till användaren. Annoteringen @CacheEvict används för detta.

  • allEntries = true: Rensar alla poster i den angivna cachen (till exempel "products").
  • Utan allEntries = true: Rensar en specifik post baserat på metodens argument (till exempel ett specifikt produkt-ID).
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

// Product and CachingApp classes as before

@Service
public class ProductService {
  // ... getProductById and updateProduct as before ...

  @CacheEvict(cacheNames = "products", key = "#id")
  public void deleteProduct(Long id) {
    System.out.println(
      "Deleting product " + id + " from DB...");
    // Simulate DB delete
    try { Thread.sleep(500); } 
    catch (InterruptedException e) {}
  }

  @CacheEvict(cacheNames = "products", allEntries = true)
  public void clearAllProductsCache() {
    System.out.println("Clearing all products from cache...");
  }
}

// Main Application
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

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

  @Bean
  public CommandLineRunner run(ProductService service) {
    return args -> {
      System.out.println("--- @CacheEvict Demo ---");
      service.getProductById(1L); // Cache product 1
      service.getProductById(2L); // Cache product 2

      System.out.println("Before delete: " + 
        service.getProductById(1L));
      service.deleteProduct(1L); // Evict product 1
      System.out.println("After delete, calling product 1 again:");
      service.getProductById(1L); // Will hit DB again

      System.out.println("Clearing all cache entries...");
      service.clearAllProductsCache();
      System.out.println("Calling product 2 after full clear:");
      service.getProductById(2L); // Will hit DB again
    };
  }
}

// Product class (same as before)
class Product {
  private Long id;
  private String name;
  public Product(Long id, String name) {
    this.id = id; this.name = name;
  }
  public Long getId() { return id; }
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
  @Override
  public String toString() {
    return "Product{" + id + ", '" + name + "'}";
  }
}

Namnge cacher och skapa anpassade nycklar

Varje cache-annotation kräver ett eller flera cacheNames (eller value) för att ange vilken cache som ska användas. Som standard genererar Spring automatiskt cache-nycklar baserat på metodparametrarna.

Du kan dock anpassa nyckeln med attributet key, som accepterar Spring Expression Language (SpEL). Det ger dig detaljerad kontroll över hur cachade poster identifieras.

  • key = "#id": Använder parametern id som cache-nyckel.
  • key = "#product.id": Använder egenskapen id hos objektet product.

Konfigurera en cachehanterare (Caffeine)

Spring Boot använder som standard en enkel cachehanterare för minnet. För mer avancerade funktioner, som tidsbaserad borttagning eller maximal storlek, kan du konfigurera en specifik CacheManager.

Så här konfigurerar du Caffeine, en populär högpresterande cache för minnet, genom att skapa en bean av typen CaffeineCacheManager. Vi definierar en cache med namnet "products", en maximal storlek och att poster ska löpa ut efter skrivning.

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;

@Configuration
public class CacheConfig {
  @Bean
  public CacheManager cacheManager() {
    CaffeineCacheManager cacheManager =
      new CaffeineCacheManager("products");
    cacheManager.setCaffeine(caffeineBuilder());
    return cacheManager;
  }

  Caffeine<Object, Object> caffeineBuilder() {
    return Caffeine.newBuilder()
      .initialCapacity(100)
      .maximumSize(500)
      .expireAfterWrite(10, TimeUnit.MINUTES)
      .recordStats();
  }
}

Snabbtest: cache-annotationer

Du har lärt dig om de centrala cache-annotationerna i Spring. Nu testar vi dina kunskaper.

Cache-lyft: repetition

Du har lärt dig att implementera cachning i din Spring Boot-applikation och på så sätt förbättra prestandan avsevärt!

  • Använd @EnableCaching för att aktivera cachning.
  • @Cacheable cachar metodresultat för snabbare läsningar.
  • @CachePut uppdaterar cacheposter efter att metoden har körts.
  • @CacheEvict tar bort poster från cachen.
  • Ange cacheNames och använd SpEL för anpassad generering av key.
  • Konfigurera en anpassad CacheManager (till exempel Caffeine) för avancerad kontroll.

Genom att använda dessa annotationer på ett genomtänkt sätt kan du minska belastningen på databasen och ge användarna en snabbare upplevelse.

Gratis att börja

Lär dig Java med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
21
Lektioner
84

Vanliga frågor

Är lektionen ”Cachning med Spring Cache” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Spring Boot 4 – komplett guide, inklusive ”Cachning med Spring Cache”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Spring Boot 4 – komplett guide innehåller totalt 4 lektioner.

Vad lär jag mig i ”Cachning med Spring Cache”?

Implementera cachningsmekanismer med Spring:s `@Cacheable` och relaterade annotationer för att förbättra svarstiderna. Ni övar på Spring Boot 4 – komplett guide med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Spring Boot 4 – komplett guide?

Du behöver inga förkunskaper. Utbildningen i Spring Boot 4 – komplett guide på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.

Hur lång tid tar lektionen ”Cachning med Spring Cache”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Spring Boot 4 – komplett guide-lektionen?

Ja. Varje Spring Boot 4 – komplett guide-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Anpassade Spring Data-repositorier
  2. Integrering av NoSQL-databaser
  3. Cachning med Spring Cache
  4. Databasmigreringar med Flyway
← Tillbaka till Spring Boot 4 – komplett guide