0Pricing
Spring Boot 4 Complete Guide · درس

التخزين المؤقت باستخدام Spring Cache

طبّق آليات التخزين المؤقت باستخدام `@Cacheable` في Spring والتعليقات التوضيحية المرتبطة بها لتحسين أزمنة الاستجابة.

التخزين المؤقت باستخدام Spring Cache درس مجاني في Spring Boot 4 Complete Guide على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Spring Boot 4 Complete Guide، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Spring Boot 4 Complete Guide 4 دروس في المجموع.

بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.

Boost Performance with Caching!

Imagine your app constantly fetching the same data from a slow database. This can make it sluggish! Caching is like having a super-fast shortcut for frequently accessed data.

Instead of going to the database every time, the app stores a copy of the data in a temporary, quick-access location (the cache). When the data is requested again, it checks the cache first.

  • Faster Responses: Users get data quicker.
  • Reduced Load: Less strain on your database or external services.

Spring Cache: Simplicity & Power

Spring Framework provides an amazing abstraction for caching. It simplifies integrating caching into your applications, so you don't have to write complex caching logic yourself.

With Spring Cache, you can use simple annotations to apply caching behavior to your methods. It supports various underlying cache providers like EhCache, Redis, or Caffeine, letting you swap them out easily without changing your code.

Getting Started: Add Dependencies

To use Spring's caching abstraction, you need to add the spring-boot-starter-cache dependency. This starter brings in Spring's caching infrastructure and a simple in-memory cache manager by default.

For a more robust in-memory cache, we'll also add Caffeine, a high-performance Java caching library.

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>

Enable Caching & @Cacheable

First, you need to enable caching in your Spring Boot application by adding the @EnableCaching annotation to your main application class or a configuration class.

Then, the @Cacheable annotation is used on a method to indicate that its result should be cached. The first time the method is called, its result is stored. Subsequent calls with the same arguments will return the cached result without executing the method.

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 in Action: Service Layer

Let's see @Cacheable on a service method. Notice the cacheNames attribute, which specifies the name of the cache where results will be stored (e.g., "products").

When getProductById is called, Spring checks the "products" cache. If a product with that ID is found, it's returned. Otherwise, the method executes (simulating a database call), and its result is cached.

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));
    };
  }
}

Keep Your Cache Fresh with @CachePut

What if you update a product? The old version might still be in the cache! The @CachePut annotation is used to update the cache with the result of a method execution.

Unlike @Cacheable, @CachePut always executes the method and then places the result into the cache. This is perfect for update operations where you want the cache to reflect the latest data.

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 + "'}";
  }
}

Clearing Cache with @CacheEvict

When an item is deleted, you want to remove it from the cache so that no stale data is accidentally served. The @CacheEvict annotation is used for this.

  • allEntries = true: Clears all entries in the specified cache (e.g., "products").
  • Without allEntries = true: Clears a specific entry based on the method's arguments (e.g., a specific product 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 + "'}";
  }
}

Naming Caches & Custom Keys

Each caching annotation requires one or more cacheNames (or value) to specify which cache to use. Spring automatically generates cache keys based on method parameters by default.

However, you can customize the key using the key attribute, which accepts Spring Expression Language (SpEL). This gives you fine-grained control over how cached entries are identified.

  • key = "#id": Uses the id parameter as the cache key.
  • key = "#product.id": Uses the id property of the product object.

Configuring a Cache Manager (Caffeine)

Spring Boot uses a simple in-memory cache manager by default. For more advanced features like time-based eviction or maximum size, you can configure a specific CacheManager.

Here's how to configure Caffeine, a popular high-performance in-memory cache, by creating a CaffeineCacheManager bean. We define a cache named "products" with a maximum size and expiration after write.

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();
  }
}

Quick Check: Cache Annotations

You've learned about the core caching annotations in Spring. Let's test your understanding.

Caching Power-Up: Recap

You've successfully learned how to implement caching in your Spring Boot application to dramatically improve performance!

  • Use @EnableCaching to activate caching.
  • @Cacheable caches method results for faster reads.
  • @CachePut updates cache entries after method execution.
  • @CacheEvict removes entries from the cache.
  • Specify cacheNames and use SpEL for custom key generation.
  • Configure a custom CacheManager (like Caffeine) for advanced control.

By intelligently using these annotations, you can reduce database load and provide a snappier experience for your users.

الأسئلة الشائعة

هل درس «التخزين المؤقت باستخدام Spring Cache» مجاني؟

نعم — نص درس «التخزين المؤقت باستخدام Spring Cache» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Spring Boot 4 Complete Guide، انتقل إلى CoddyKit PRO. تتضمن دورة Spring Boot 4 Complete Guide 4 دروس في المجموع.

ماذا ستتعلم في «التخزين المؤقت باستخدام Spring Cache»؟

طبّق آليات التخزين المؤقت باستخدام `@Cacheable` في Spring والتعليقات التوضيحية المرتبطة بها لتحسين أزمنة الاستجابة. تتمرن على Spring Boot 4 Complete Guide مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Spring Boot 4 Complete Guide؟

لا تُشترط خبرة سابقة. Spring Boot 4 Complete Guide على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «التخزين المؤقت باستخدام Spring Cache»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Spring Boot 4 Complete Guide هذا؟

نعم. كل درس في Spring Boot 4 Complete Guide يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. مستودعات Spring Data مخصّصة
  2. دمج قواعد بيانات NoSQL
  3. التخزين المؤقت باستخدام Spring Cache
  4. ترحيل قواعد البيانات باستخدام Flyway
← العودة إلى Spring Boot 4 Complete Guide