@Cacheable
批注的应用, @Cacheable
批注用于标记返回值将存储在缓存中的方法。 但是, @Cacheable
只是Spring的Guy为缓存而设计的一对注释中的一个,另一个是@CacheEvict
。 像@Cacheable
一样, @CacheEvict
具有value
, key
和condition
属性。 它们的工作方式与@Cacheable
支持的方式@Cacheable
,因此有关它们的更多信息,请参见我以前的博客: Spring 3.1 Caching和@Cacheable 。
CacheEvict
支持两个附加属性: allEntries
和beforeInvocation
。 如果我是一个赌博的人,我会花钱买最受欢迎的allEntries
。 allEntries
用于完全清除@CacheEvict
的强制value
参数定义的高速缓存的内容。 下面的方法演示了如何应用allEntries
:
@CacheEvict(value = "employee", allEntries = true)public void resetAllEntries() {// Intentionally blank}
resetAllEntries()
将@CacheEvict
的allEntries
属性设置为“ true”,并假定findEmployee(...)
方法如下所示:
@Cacheable(value = "employee")public Person findEmployee(String firstName, String surname, int age) {return new Person(firstName, surname, age);}
…然后在下面的代码resetAllEntries()
,将清除“员工”缓存。 这意味着在JUnit测试中, employee1
下面不会引用与employee2
相同的对象:
@Testpublic void testCacheResetOfAllEntries() {Person employee1 = instance.findEmployee("John", "Smith", 22);instance.resetAllEntries();Person employee2 = instance.findEmployee("John", "Smith", 22);assertNotSame(employee1, employee2);}
第二个属性是beforeInvocation
。 这确定在调用方法之前或之后是否从缓存中清除数据项。
下面的代码非常荒谬。 但是,它确实表明您可以同时将@CacheEvict
和@Cacheable
应用于方法。
@CacheEvict(value = "employee", beforeInvocation = true)@Cacheable(value = "employee")public Person evictAndFindEmployee(String firstName, String surname, int age) {return new Person(firstName, surname, age);}
在上面的代码中, @CacheEvict
会在@Cacheable
搜索缓存之前,使用匹配的键删除缓存中的所有条目。 由于@Cacheable
找不到任何条目,因此它将调用我的代码,将结果存储在缓存中。 对我的方法的后续调用将调用@CacheEvict
,它将删除任何适当的条目,结果是在JUnit测试中变量下的employee1
将永远不会引用与employee2
相同的对象:
@Testpublic void testBeforeInvocation() {Person employee1 = instance.evictAndFindEmployee("John", "Smith", 22);Person employee2 = instance.evictAndFindEmployee("John", "Smith", 22);assertNotSame(employee1, employee2);}
就像我在上面说的那样,由于我将@Cacheable
和@CacheEvict
都@Cacheable
同一方法, evictAndFindEmployee(...)
似乎有点荒谬。 但是,更重要的是,它使代码不清楚并违反了单一责任原则。 因此,我建议创建单独的可缓存和缓存退出方法。 例如,如果您有一个缓存方法,例如:
@Cacheable(value = "employee", key = "#surname")public Person findEmployeeBySurname(String firstName, String surname, int age) {return new Person(firstName, surname, age);}
然后,假设您需要比简单的“清除所有”更好的缓存控制,则可以轻松定义其对应项:
@CacheEvict(value = "employee", key = "#surname")public void resetOnSurname(String surname) {// Intentionally blank}
这是使用了已应用于同一规划环境地政司表达一个简单的空白标记方法@Cacheable
驱逐所有的Person
,从其中关键的“姓”的说法相匹配的缓存实例。
@Testpublic void testCacheResetOnSurname() {Person employee1 = instance.findEmployeeBySurname("John", "Smith", 22);instance.resetOnSurname("Smith");Person employee2 = instance.findEmployeeBySurname("John", "Smith", 22);assertNotSame(employee1, employee2);}
在上面的代码中,对findEmployeeBySurname(...)
的首次调用创建了一个Person
对象,Spring将其定义为“ Smith”的键存储在“员工”缓存中。 对resetOnSurname(...)
的调用会清除“员工”缓存中所有姓为“ Smith”的条目,最后第二次对findEmployeeBySurname(...)
调用将创建一个新的Person
对象,Spring再次将其存储在“员工”缓存,并带有“史密斯”键。 因此,变量employee1
和employee2
没有引用相同的对象。
涵盖了Spring的缓存注释之后,下一个难题是研究设置实用的缓存:您如何启用Spring缓存以及应使用哪种缓存实现? 稍后再说……
祝您编程愉快,别忘了分享!
参考:来自Captain Debug博客博客的JCG合作伙伴 Roger Hughes的Spring 3.1 Caching和@CacheEvict 。
翻译自: https://www.javacodegeeks.com/2012/09/spring-31-caching-and-cacheevict.html