“This article has participated in the call for good writing activities, click to view: the back end, the big front end double track submission, 20,000 yuan prize pool waiting for you to challenge!”

In version 3.1, Spring provides a caching strategy based on annotations, which is very smooth to use in practice. This article will briefly introduce several commonly used annotations. If you need them, you can try them out

The main knowledge points of this article:

  • @cacheable: if a cache exists, use it. If not, the method is executed and the result is stuffed into the cache
  • @cacheevit: Invalidated cache
  • @cachePUT: Updates the cache

I. Project environment

1. Project dependencies

This project is developed by SpringBoot 2.2.1.RELEASE + Maven 3.5.3 + IDEA + redis5.0

Open a Web service for testing

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
</dependencies>
Copy the code

Use the default configuration for the whole process, redis native, port 6379, no password

II. Introduction to cache annotations

1. @Cacheable

This annotation is used to modify the method or class. When we access the method it modifies, we get the value from the cache first. If it exists in the cache, we get the value directly from the cache. When the cache does not exist, the method is executed and the result is written to the cache

There are two core Settings for this annotation

/ / @aliasfor ("cacheNames") String[] value() default {}; @AliasFor("value") String[] cacheNames() default {}; /** * cache key */ String key() default "";Copy the code

CacheNames is the prefix of the cache key, and can be the key variable cached by the component. When key is not set, use the method argument to initialize it. Note that key is an SpEL expression, so if you want to write a string, enclose it in single quotes

A simple use pose

/** * select * from cache; Otherwise, execute the method and cache the result * <p> * redisKey: cacheNames + key combination --> Support SpEL * redisValue: return result * *@param name
 * @return* /
@Cacheable(cacheNames = "say", key = "'p_'+ #name")
public String sayHello(String name) {
    return "hello+" + name + "-- >" + UUID.randomUUID().toString();
}
Copy the code

If we pass yihuihui, the cache key is say::p_yihuihui

In addition to the above three configuration values, if you look at the @cacheable annotation source code, you’ll see the condition setting, which indicates that the condition it sets is not written to the cache until the condition it sets has been fulfilled

/** * only if the condition is met is written to cache **@param age
 * @return* /
@Cacheable(cacheNames = "condition", key = "#age", condition = "#age % 2 == 0")
public String setByCondition(int age) {
    return "condition:" + age + "-- >" + UUID.randomUUID().toString();
}
Copy the code

In this case, the cache is only removed if age is even; Otherwise, the cache is not written

Next comes the unless parameter, which, as the name suggests, indicates that the condition is not written to the cache

/** * unless the condition is not met before writing to the cache **@param age
 * @return* /
@Cacheable(cacheNames = "unless", key = "#age", unless = "#age % 2 == 0")
public String setUnless(int age) {
    return "unless:" + age + "-- >" + UUID.randomUUID().toString();
}
Copy the code

2. @CachePut

Writes the return result of the method to the cache, regardless of whether the cache is present or not; Applies to cache updates

/** * writes to the cache regardless of whether the cache exists@param age
 * @return* /
@CachePut(cacheNames = "t4", key = "#age")
public String cachePut(int age) {
    return "t4:" + age + "-- >" + UUID.randomUUID().toString();
}
Copy the code

3. @CacheEvict

This is what we mean by delete cache

/** * invalid cache **@param name
 * @return* /
@CacheEvict(cacheNames = "say", key = "'p_'+ #name")
public String evict(String name) {
    return "evict+" + name + "-- >" + UUID.randomUUID().toString();
}
Copy the code

4. @Caching

In actual work, it is common to encounter a scenario where data changes and multiple caches are updated. For this scenario, @Caching can be implemented

/** * Caching Implements a combination, adding caches and invalidating other caches **@param age
 * @return* /
@Caching(cacheable = @Cacheable(cacheNames = "caching", key = "#age"), evict = @CacheEvict(cacheNames = "t4", key = "#age"))
public String caching(int age) {
    return "caching: " + age + "-- >" + UUID.randomUUID().toString();
}
Copy the code

This is the combined operation

  • fromcaching::ageCache data, do not exist when the execution method and write to the cache;
  • Failure of the cachet4::age

5. What happens to the cache when an exception occurs?

In the above cases, which are all normal scenarios, how will the cache behave when the method throws an exception?

/** * tests whether an exception will be written to the cache **@param age
 * @return* /
@Cacheable(cacheNames = "exception", key = "#age")
@Cacheable(cacheNames = "say", key = "'p_yihuihui'")
public int exception(int age) {
    return 10 / age;
}
Copy the code

According to the measured results, when age==0, neither of the above two caches will succeed

Test cases

Next verify that the cache annotations are consistent with those described above

@RestController
public class IndexRest {
    @Autowired
    private BasicDemo helloService;

    @GetMapping(path = {"", "/"})
    public String hello(String name) {
        returnhelloService.sayHello(name); }}Copy the code

This is mainly to validate the @cacheable annotation. If the cache is not hit, it should return a different result each time, but when it is accessed, it will return the same result each time

curl http://localhost:8080/? name=yihuihuiCopy the code

Failure of the cache

@GetMapping(path = "evict")
public String evict(String name) {
    return helloService.evict(String.valueOf(name));
}
Copy the code

Invalidation caching needs to be used in conjunction with case above

curl http://localhost:8080/evict? name=yihuihui curl http://localhost:8080/? name=yihuihuiCopy the code

The rest of the related test classes are easier to understand, and post the corresponding code

@GetMapping(path = "condition")
public String t1(int age) {
    return helloService.setByCondition(age);
}

@GetMapping(path = "unless")
public String t2(int age) {
    return helloService.setUnless(age);
}

@GetMapping(path = "exception")
public String exception(int age) {
    try {
        return String.valueOf(helloService.exception(age));
    } catch (Exception e) {
        returne.getMessage(); }}@GetMapping(path = "cachePut")
public String cachePut(int age) {
    return helloService.cachePut(age);
}
Copy the code

7. Summary

Finally, a management summary of several caching annotations provided by Spring

  • @Cacheable: Cache exists, then cache access; Otherwise, the method is executed and the result returned is written to the cache
  • @CacheEvit: invalidation cache
  • @CachePutUpdate cache
  • @Caching: all annotation combination

Although the above can meet the common cache usage scenarios, but there is a very important point does not specify how to set the cache expiration time??

How to set different cache expiration time for each cache, we will see you in the next blog post, I am a gray, welcome to pay attention to the public account of long cao gray blog

III. Can’t miss the source code and related knowledge points

0. Project

  • Project: github.com/liuyueyi/sp…
  • Source: github.com/liuyueyi/sp…

1. An ashy Blog

As far as the letter is not as good, the above content is purely one’s opinion, due to the limited personal ability, it is inevitable that there are omissions and mistakes, if you find bugs or have better suggestions, welcome criticism and correction, don’t hesitate to appreciate

Below a gray personal blog, record all the study and work of the blog, welcome everyone to go to stroll

  • A grey Blog Personal Blog blog.hhui.top
  • A Grey Blog-Spring feature Blog Spring.hhui.top