在Spring Boot缓存API - Code Factory


Spring在缓存方面具有一些不错的功能,并且使用Spring缓存API的抽象非常简单。
缓存是一种增强系统性能的机制。它是位于应用程序和持久数据库之间的临时内存。高速缓存存储器存储最近使用的数据项,以尽可能减少数据库命中的次数。
Spring框架为不同的缓存提供程序提供了缓存抽象api。API的用法非常简单,但功能非常强大。今天,我们将在缓存中看到基于注释的Java配置。注意,我们也可以通过XML配置实现类似的功能。

@EnableCaching
它启用了Spring的注释驱动的缓存管理功能。在spring boot项目中,我们需要将其添加到带有注释的启动应用程序类中@SpringBootApplication。Spring提供了一个并发哈希图作为默认缓存,但是我们也可以重写CacheManager以轻松注册外部缓存提供程序。

@Cacheable
它在方法级别上用于使spring知道该方法的响应是可缓存的。Spring管理此方法对注释属性中指定的缓存的请求/响应。例如,@Cacheable ("cacheName1", “cacheName2”)。
@Cacheable注释具有更多选项。就像我们可以从方法的请求中指定缓存的键一样。如果未指定任何内容,spring将使用所有类字段并将其用作缓存键(主要是HashCode)来维护缓存,但是我们可以通过提供键信息来覆盖此行为。

@Cacheable(value="employee", key="location")
public Employee findEmployee(Location location)
@Cacheable(value=
"employee", key="location.name")
public Employee findEmployee(Location location)
@Cacheable(value=
"employee", key="T(classType).hash(location)")
public Employee findEmployee(Location location)

我们还可以使用条件缓存。例如:

@Cacheable(value="employee", key="locationName.length > 5")
public Employee findEmployee(String locationName)

@CachePut
有时我们需要手动操作缓存,以在方法调用之前放置(更新)缓存。这将允许我们更新缓存,也将允许执行该方法。该方法将始终执行,并将其结果放入缓存(根据@CachePut选项)。
它支持与@Cacheable缓存填充相同的选项,应该用于缓存填充,而不是方法流优化。

请注意,通常不建议在同一方法上使用@CachePut和@Cacheable批注,因为它们的行为不同。后者导致通过使用缓存跳过方法执行,而前者则强制执行以便执行缓存更新。
这会导致意外的行为,并且除了特定的极端情况(例如具有相互排斥条件的注释)外,应避免此类声明。

@CacheEvict
当我们需要移出(删除)先前加载的主数据的缓存时使用它。当执行CacheEvict注释的方法时,它将清除缓存。
我们可以在此处指定键以删除缓存,如果需要删除缓存的所有条目,则需要使用allEntries=true。当需要清除整个缓存区域时,此选项非常有用–而不是删除每个条目(由于效率低下,这将需要很长时间),所有条目都将在一次操作中被删除。

@Caching
当我们需要双方都需要CachePut和CacheEvict。

SpringBootCachingApplication.java案例:

@SpringBootApplication
@EnableCaching
public class SpringBootCachingApplication {
public static void main(String[] args) {
  SpringApplication.run(SpringBootCachingApplication.class, args);
 }
}

StudentController.java:

@RestController
public class StudentController {
@Autowired
 StudentService studentService;
 
 @GetMapping("/student/{id}")
 public Student findStudentByID(@PathVariable String id) {
  System.out.println(
"Student ID : " + id);
  return studentService.getStudentByID(id);
 }
}

Student.java:

public class Student {
String id;
 String name;
 int age;
 
 public Student(String id, String name, int age) {
  this.id = id;
  this.name = name;
  this.age = age;
 }
public String getId() {
  return id;
 }
public void setId(String id) {
  this.id = id;
 }
public String getName() {
  return name;
 }
public void setName(String name) {
  this.name = name;
 }
public int getAge() {
  return age;
 }
public void setAge(int age) {
  this.age = age;
 }
}

StudentService.java:

@Service
public class StudentService {
@Cacheable("student")
 public Student getStudentByID(String id) {
  try {
   System.out.println(
"Sleep for 5 seconds.");
   Thread.sleep(5000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  return new Student(
"1", "Code Factory", 18);
 }
}

访问:http://localhost:8080/student/1

您将得到一个对象的JSON响应Student。需要注意的是,第一次响应至少需要5秒钟,然后相同URL的后续响应会更快。