Spring Caching

Caching Data with Spring

This guide walks you through the process of enabling caching on a Spring managed bean.

What You Will build

You will build an application that enables caching on a simple book repository.

Create a Book Model

First, you need to create a simple model for your book. The following listing (from src/main/java/com/example/caching/Book.java) shows how to do so

public class Book {
    private String isbn;
    private String title;
}

Create a Book Repository

You also need a repository for that model.

public interface BookRespository {
    Book getByIsbn(String isbn);
}

implement, or use spring data

@Component
public class SimpleBookRepository implements BookRepository {
    //...
}

Using the Repository

You also need a CommandLineRunner that injects the BookRepository and calls it several times

@Component
class AppRunner implements CommandLineRunner {
    
    private static final Logger looger = LoggerFactory.getLogger(AppRunner.class);
    
    private final BookRepository bookRepository;
    
    public AppRunner(BookRepository bookRepository) {
        this.bookRespository = bookRepository;
    }
    
    public void run(String... args) {
        logger.info("Fetching books...");
        logger.info(bookRepository.getByIsbn("isbn-1234"));
        logger.info(bookRepository.getByIsbn("isbn-4567"));
        logger.info(bookRepository.getByIsbn("isbn-1234"));
    }
}

Enable caching

Now you can enable caching on your SimpleBookRepository so that the books are cached within the books cache. The following listing (from src/main/java/com/example/caching/SimpleBookRepository.java) shows the repository definition:

@Component
class SimpleBookRepository implements BookRepository {
    
    @Override
    @Cacheable("books")
    public Book getByIsbn(String isbn) {
        simulateSlowService();
    	return new Book(isbn, "Some book");
    }
    //。。。
}

You now need to enable the processing of the caching annotations,

@SpringBootApplication
@EnableCaching
public class CachingApplication {...}

The @EnableCaching annotation triggers a post-processor that inspects every Spring bean for the presence of caching annotations on public methods. If such an annotation is found, a proxy is automatically created to intercept the method call and handle the caching behavior accordingly.

The post-processor handles the @Cacheable, @CachePut and @CacheEvict annotations. You can refer to the Javadoc and the reference guide for more detail.

Spring Boot automatically configures a suitable CacheManager to serve as a provider for the relevant cache. See the Spring Boot documentation for more detail.

Our sample does not use a specific caching library, so our cache store is the simple fallback that uses ConcurrentHashMap. The caching abstraction supports a wide range of cache libraries and is fully compliant with JSR-107 (JCache).

[^compliant ]: 顺从的 符合的

Integration

https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#cache

Cache Abstraction

Since version 3.1, the Spring Framework provides support for transparently adding caching to an existing Spring application. Similar to the transaction support, the caching abstraction allows consistent use of various caching solutions with minimal impact on the code.

In Spring Framework 4.1, the cache abstraction was significantly extended with support for JSR-107 annotations and more customization options.

Understanding the Cache Abstraction

At its core, the cache abstraction applies caching to Java methods, thus reducing the number of executions based on the information available in the cache. That is, each time a targeted method is invoked, the abstraction applies a caching behavior that checks whether the method has been already invoked for the given arguments. If it has been invoked, the cached result is returned without having to invoke the actual method. If the method has not been invoked, then it is invoked, and the result is cached and returned to the user so that, the next time the method is invoked, the cached result is returned. This way, expensive methods (whether CPU- or IO-bound) can be invoked only once for a given set of parameters and the result reused without having to actually invoke the method again. The caching logic is applied transparently without any interference to the invoker.

The caching abstraction provides other cache-related operations, such as the ability to update the content of the cache or to remove one or all entries. These are useful if the cache deals with data that can change during the course of the application.

As with other services in the Spring Framework, the caching service is an abstraction (not a cache implementation) and requires the use of actual storage to store the cache data — that is, the abstraction frees you from having to write the caching logic but does not provide the actual data store. This abstraction is materialized by the org.springframework.cache.Cache and org.springframework.cache.CacheManager interfaces.

Spring provides a few implementations of that abstraction: JDK java.util.concurrent.ConcurrentMap based caches, Ehcache 2.x, Gemfire cache, Caffeine, and JSR-107 compliant caches (such as Ehcache 3.x). See Plugging-in Different Back-end Caches for more information on plugging in other cache stores and providers.

The caching abstraction has no special handling for multi-threaded and multi-process environments, as such features are handled by the cache implementation.

If you have a multi-process environment (that is, an application deployed on several nodes), you need to configure your cache provider accordingly. Depending on your use cases, a copy of the same data on several nodes can be enough. However, if you change the data during the course of the application, you may need to enable other propagation mechanisms.

Caching a particular item is a direct equivalent of the typical get-if-not-found-then-proceed-and-put-eventually code blocks found with programmatic cache interaction. No locks are applied, and several threads may try to load the same item concurrently. The same applies to eviction. If several threads are trying to update or evict data concurrently, you may use stale data. Certain cache providers offer advanced features in that area. See the documentation of your cache provider for more details.

img

To use the cache abstraction, you need to take care of two aspects:

  • Caching declaration: Identify the methods that need to be cached and their policy.
  • Cache configuration: The backing cache where the data is stored and from which it is read.

Declarative Annotation-based Caching

For caching declaration, Spring’s caching abstraction provides a set of Java annotations:

  • @Cacheable: Triggers cache population.
  • @CacheEvict: Triggers cache eviction.
  • @CachePut: Updates the cache without interfering with the method execution.
  • @Caching: Regroups multiple cache operations to be applied on a method.
  • @CacheConfig: Shares some common cache-related settings at class-level.
Default Key Generation

Since caches are essentially key-value stores, each invocation of a cached method needs to be translated into a suitable key for cache access.

Default Cache Resolution

The caching abstraction uses a simple CacheResolver that retrieves the caches defined at the operation level by using the configured CacheManager.

To provide a different default cache resolver, you need to implement the org.springframework.cache.interceptor.CacheResolver interface.

Custom Cache Resolution

The default cache resolution fits well for applications that work with a single CacheManger and have no complex cache resolution requirements.

For applications that work with several cache managers, you can set the cacheManger to use for each operation, as the following example shows:

@Cacheable(cacheNames="books", cacheManager="anotherCacheManager")  public Book findBook(ISBN isbn) {...}

Configuring the Cache Storage

The cache abstraction provides several storage integration options. To use them, you need to declare an appropriate CacheManager (an entity that controls and manages Cache instances and that can be used to retrieve these for storage).

JDK ConcurrentMap-based Cache

The JDK-based Cache implementation resides under org.springframework.cache.concurrent package.

CacheManager

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值