Spring Boot 缓存
缓存
缓存是一种提高应用程序性能的方式。它储存在应用和持久数据库之间。高速缓存储存之前使用过的数据,以便尽可能减少数据库的调用。
优点
将通常会重复使用的数据缓存是一个非常有效的提高应用程序速度的方法。我们将频繁请求的数据存在内存中,以避免在用户每次需要数据时都要调用高消耗的服务后端。来自内存的数据访问确实比来自数据库、文件系统等存储的数据访问或其他服务调用要快。
缓存和缓冲区之间的区别
缓存 | 缓冲区 |
---|---|
使用最近使用方案 | 使用先进先出方案 |
长寿命 | 短寿命 |
取决于页面缓存大小 | 取决于内存中的原始块I/O区 |
从缓存读 | 写入缓冲区 |
提高读取性能 | 提高写入性能 |
Spring Boot缓存注解
Spring Boot为以下缓存提供商提供集成方法:
- JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan, and others)
- EhCache 2.x
- Hazelcast
- Infinispan
- Couchbase
- Redis
- Caffeine
- Simple Cache
在class path中提供上述默认缓存提供商选项后,Spring boot会自动配置缓存。缓存功能在应用中可以通过 @EnableCaching
生效。
Maven
在 spring-boot-starter-cache
库中包含缓存的模组
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
@EnableCaching
通过
@Enablecaching
注解可以启用缓存。如果当前没有 CacheManager 的实例被创建,则创建一个实例。它会扫描一个测定的提供商,如果当前没有缓存提供商,则它会使用同步HashMap来建立一个内存缓存。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class SpringBootCachingApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootCachingApplication.class, args);
}
}
@Cacheable
Cacheable是方法级别的注解。它为方法的返回值特定一个缓存。@Cacheable 注解将结果储存到缓存区。
本例中,我们主要的目标是将数据缓存在服务层,其中,我们会主动延迟请求恢复时间,以模拟实际的服务端调用。由于程序的模拟等待,第一次点击请求的响应将有一个延迟,而后续的调用将会得到明显更快的响应。
在第一次调用中,Employee的值会从数据库中取得,并储存在缓存中。在第二次调用中,Employee的值会从缓存中取得。
package com.techgeeknext.service;
import com.techgeeknext.caching.annotation.CustomEmployeeCachingAnnotation;
import com.techgeeknext.data.Employee;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class EmployeeServiceImpl implements EmployeeService {
private static final Logger logger = LoggerFactory.getLogger(EmployeeServiceImpl.class);
private List<Employee> employees = new ArrayList<>();
/**
* Method to get the employee default values
* First time, it'' get from database
* Next time onwards it will get it from Cache
*
* @return employees
*/
@Override
@Cacheable("employees")
public List<Employee> getEmployees() {
retrieveDataFromDatabase();
logger.info("----Getting employee data from database.----");
return employees;
}
/**
* Create static employees data
* @param employees
*/
private void createEmployeesData(List<Employee> employees) {
employees.add(Employee.builder().id(1).name("TechGeekNextUser1").role("Admin").build());
employees.add(Employee.builder().id(2).name("TechGeekNextUser2").role("User").build());
employees.add(Employee.builder().id(3).name("TechGeekNextUser3").role("Supervisor").build());
}
@Override
@CustomEmployeeCachingAnnotation
public Employee getEmployeeById(Integer employeeId) {
retrieveDataFromDatabase();
logger.info("----Getting employee data from database.----");
return employees.get(employeeId);
}
/**
* Added sleep for 4 second to mimic for database call
*/
private void retrieveDataFromDatabase() {
try {
createEmployeesData(employees);
logger.info("----Sleep for 4 Secs.. to mimic like it's a backend call.-----");
Thread.sleep(1000 * 4);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
并且我们创建了 CustomCaching
类,并在上述类中使用。
package com.techgeeknext.caching.annotation;
import org.springframework.cache.annotation.Cacheable;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Cacheable(cacheNames = "product")
public @interface CustomEmployeeCachingAnnotation {
}
@CachePut
这是一个方法级别的注解。用于更新缓存而不干扰方法的执行。
@Cacheable和@CachePut注解区别在于,@Cacheable注解跳过执行,@CachePut注解执行方法并缓存结果。
@CachePut(cacheNames="employee", key="#id") //updating cache
public Employee updateEmployee(int id, Employee employeeData)
{
//some code
}
@CacheEvict
用于删除陈旧或不再使用的缓存数据
-
将所有缓存都丢弃,删除所有缓存数据。
//removing all entries of employee from the cache @CacheEvict(value="employee", allEntries=true) public String getEmployee(int id) { //some code }
-
根据关键字丢弃某一个缓存
@CacheEvict(key="#employee.name")
@Caching
方法级别的注解,需要对多个缓存操作进行重新分组时使用。
@CacheEvict("employees")
@CacheEvict(value="item", key="#key")
public List<Employee> getEmployees()() {...}
上述操作可以使用@Caching注解放在一起。@Caching注解提供了一个解决方案,可以同时处理多个用例。
@Caching(evict = { @CacheEvict("employees"),
@CacheEvict(cacheNames="item", key="#key") })
public List<Employee> getEmployees()() {...}
@CacheConfig
类级别注解,让Spring存储整个类的缓存。
@CacheConfig(cacheNames={"employee"})
public class EmployeeService
{
//some code
}