SpringBoot——spring cache(十八)

前言

在我们不使用其他第三方缓存依赖的时候,springboot自动采用ConcurrenMapCacheManager作为缓存管理器。

缓存注解

对于缓存声明,spring的缓存提供了一组java注解:

  • @Cacheable:触发缓存写入。
  • @CacheEvict:触发缓存清除。
  • @CachePut:更新缓存(不会影响到方法的运行)。
  • @Caching:重新组合要应用于方法的多个缓存操作。
  • @CacheConfig:设置类级别上共享的一些常见缓存设置。

@Cacheable注解

可以用来进行缓存的写入,将结果存储在缓存中,以便于在后续调用的时候可以直接返回缓存中的值,而不必再执行实际的方法。

最简单的使用方式,注解名称=缓存名称,使用例子如下:

1
2
  @Cacheable("books")
public Book findBook(ISBN isbn) {...}

一个方法可以对应两个缓存名称,如下:

1
2
@Cacheable({"books", "isbns"})
public Book findBook(ISBN isbn) {...}

缓存名称是可以配置动态参数的,比如选择传入的参数:

1
2
3
4
5
6
7
8
@Cacheable(cacheNames="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

@Cacheable(cacheNames="books", key="#isbn.rawNumber")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

@Cacheable(cacheNames="books", key="T(someType).hash(#isbn)")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

还可以设置根据条件判断是否需要缓存 condition:取决于给定的参数是否满足条件; unless:取决于返回值是否满足条件。

以下是一个简单的例子:

1
2
3
4
5
@Cacheable(cacheNames="book", condition="#name.length() < 32") 
public Book findBook(String name)

@Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result.hardback")
public Book findBook(String name)

还可以设置:keyGenerator(指定key自动生成方法),cacheManager(指定使用的缓存管理),cacheResolver(指定使用缓存的解析器)等,这些参数比较适合全局设置,这里就不多做介绍了。

@CachePut注解

始终执行该方法,并将结果放入缓存,注解参数与@Cacheable相同。

CacheEvict注解

删除缓存的注解,这对删除旧的数据和无用的数据是非常有用的。

这里还多了一个参数(allEntries),设置allEntries=true时,可以对整个条目进行批量删除。

以下是个简单的例子:

1
2
3
4
5
6
@CacheEvict(cacheNames="books") 
public void loadBooks(InputStream batch)

//对cacheNames进行批量删除
@CacheEvict(cacheNames="books", allEntries=true)
public void loadBooks(InputStream batch)

@Caching注解

在使用缓存的时候,有可能会同时进行更新和删除,会出现同时使用多个注解的情况.而@Caching可以实现。

以下是个简单的例子:

1
2
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
public Book importBooks(String deposit, Date date)

@CacheConfig注解

缓存提供了许多的注解选项,但是有一些公用的操作,我们可以使用@CacheConfig在类上进行全局设置。

以下是个简单的例子:

1
2
3
4
5
6
@CacheConfig("books") 
public class BookRepositoryImpl implements BookRepository {

@Cacheable
public Book findBook(ISBN isbn) {...}
}

依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>

开启缓存支持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.qn;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

import java.util.Arrays;

/**
* @ServletComponentScan 扫描Servlet, Filter, Listener 添加到容器
*/
@MapperScan("com.qn.mapper") //扫描的mapper
@SpringBootApplication
@ServletComponentScan
@EnableCaching
public class SpringbootDemoApplication {

public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class, args);
}

@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
// 开始检查spring boot 提供的 beans
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
};
}
}

缓存操作

数据库上几章已经应用,这里直接在数据库操作的地方加入缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.qn.service;

import com.qn.eneity.User;
import com.qn.dao.boot.UserMapperAnocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
* 注解使用mybatis业务类
*/
@Service
public class UserServiceAnocation {
@Autowired
UserMapperAnocation userMapperAnocation;

@Cacheable("user")
public List<User> getAllUsers() {
System.out.println(new Date().toString());
return userMapperAnocation.getAllUsers();
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.qn.service;

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest
@RunWith(SpringRunner.class)
class UserServiceAnocationTest {

@Autowired
UserServiceAnocation userServiceAnocation;

@Test
void getAllUsers() {
for (int i = 0; i < 10; i++) {
userServiceAnocation.getAllUsers()
.forEach(user -> System.out.println(user.toString()));
}
}
}

![SpringBoot——spring cache(十八)_2020-05-22-15-33-32.png](/images/SpringBoot——spring cache(十八)_2020-05-22-15-33-32.png)

文章目录
  1. 1. 前言
  2. 2. 缓存注解
    1. 2.1. @Cacheable注解
    2. 2.2. @CachePut注解
    3. 2.3. CacheEvict注解
    4. 2.4. @Caching注解
  3. 3. @CacheConfig注解
  4. 4. 依赖
  5. 5. 开启缓存支持
  6. 6. 缓存操作
  7. 7. 测试
|