@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