Spring框架为不同的缓存产品提供缓存抽象api,API的使用非常简单,但功能非常强大。今天我们将在缓存上看到基于注释的Java配置,请注意,我们也可以通过XML配置实现类似的功能。
@EnableCaching
它支持Spring的注释驱动的缓存管理功能,在spring boot项目中,我们需要将它添加到带注释的引导应用程序类中@SpringBootApplication。Spring默认提供了一个并发hashmap作为缺省缓存,但我们也可以覆盖CacheManager以轻松注册外部缓存提供程序。
@Cacheable
它在方法级别上使用,让spring知道该方法的响应是可缓存的。Spring将此方法的请求/响应管理到注释属性中指定的缓存。例如,@Cacheable ("cache-name1", “cache-name2”)。
@Cacheable注释有更多选项。就像我们可以从方法的请求中指定缓存的键,如果没有指定,spring使用所有类字段并将其用作缓存键(主要是HashCode)来维护缓存,但我们可以通过提供关键信息来覆盖此行为:
@Cacheable(value="books", key="#isbn")
public Book findStoryBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@Cacheable(value="books", key="#isbn.rawNumber")
public Book findStoryBook (ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@Cacheable(value="books", key="T(classType).hash(#isbn)")
public Book findStoryBook (ISBN isbn, boolean checkWarehouse, boolean includeUsed)
我们也可以使用条件缓存。例如,
@Cacheable(value="book", condition="#name.length < 50")
public Book findStoryBook (String name)
@CachePut
有时我们需要手动操作缓存,这样可在方法调用之前put(更新)缓存,这个方法让我们更新缓存,并且执行被注释的该方法,Spring执行注释方法,并将其结果放入缓存中(根据@CachePut选项)。
它与@Cacheable支持相同的选项,应该用于缓存填充,而不是方法流优化。
请注意,通常不鼓励对同一方法使用@CachePut和@Cacheable注释,因为它们具有不同的行为。虽然后者导致通过使用缓存跳过方法执行,但前者强制执行以执行缓存更新。
这会导致意外的行为,除了特定的角落情况(例如注释具有将它们彼此排除的条件)之外,应该避免这种声明。
@CacheEvict
当我们需要从缓存删除先前加载的主数据时可以使用它,当CacheEvict注释方法将被执行时,它将清除缓存。
我们可以在这里指定键来删除缓存,如果我们需要删除缓存的所有条目,那么我们需要使用allEntries=true。当需要清除整个缓存区域时,此选项会派上用场 - 而不是逐个剔除每个条目(这会花费很长时间,因为它效率低),所有条目都在一次操作中被删除。
@Caching
当同时需要CachePut和CacheEvict时,使用这个注释。
Spring启动提供与以下缓存提供程序的集成。Spring引导使用默认选项进行自动配置,如果这些选项存在于类路径中,并且我们已在spring boot应用程序中通过@EnableCaching启用了缓存。
JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan, and others)
EhCache 2.x
Hazelcast
Infinispan
Couchbase
Redis
Caffeine
Simple cache
我们可以通过覆盖缓存提供程序特定的设置来覆盖Spring starter中的特定缓存行为 - 例如
spring.cache.infinispan.config=infinispan.xml
使用案例
1. 使用缓存:
@Service
public class StudentService
{
@Cacheable("student")
public Student getStudentByID(String id)
{
try
{
System.out.println("Going to sleep for 5 Secs.. to simulate backend call.");
Thread.sleep(1000*5);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return new Student(id,"Sajal" ,"V");
}
}
服务层方法被注释@Cacheable("student"),该注释在该特定方法中启用高速缓存,并且高速缓存名称是"student"。
在该getStudentByID()方法中,我们使用有意的5秒延迟Thread.sleep(1000*5)。这只是为了了解响应是来自缓存还是真正的后端。
2. REST前端:
@RestController
public class StudentController
{
@Autowired
StudentService studentService;
@GetMapping("/student/{id}")
public Student findStudentById(@PathVariable String id)
{
System.out.println("Searching by ID : " + id);
return studentService.getStudentByID(id);
}
}
3.启用缓存:
@SpringBootApplication
@EnableCaching
public class SpringCacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCacheApplication.class, args);
}
}