Spring Framework提供了對將緩存透明添加到現有Spring應用程序中的支持。 與事務支持類似,緩存抽象允許一致使用各種緩存解決方案,而對代碼的影響最小。
從本質上講,抽象將緩存應用于Java方法,從而基于緩存中可用的信息減少了執行次數。 也就是說,每次調用目標方法時,抽象將應用緩存行為,以檢查該方法是否已針對給定參數執行。 如果有,則返回緩存的結果,而不必執行實際的方法; 如果還沒有,則執行該方法,將結果緩存并返回給用戶,以便下次調用該方法時,返回緩存的結果。
這個概念當然不是什么新鮮事物。 您可以查看Spring,AspectJ,Ehcache方法的緩存Aspect是我們JCG合作伙伴之一Brian Du Preez撰寫的一篇非常有趣的文章,其中使用了Aspect Oriented Programming 。
顧名思義,“緩存抽象”不是實際的實現,因此它需要使用實際的存儲來存儲緩存數據。 您可能已經猜到了,開箱即用地提供了Ehcache支持。 還有一個基于JDK的ConcurrentMap的實現,您實際上可以插入不同的后端緩存 。
現在,讓我們看一些有關緩存抽象的示例代碼。 為此,我將使用JCG的另一位合作伙伴 James Carr 在Spring 3.1.0.M1中提供的非常有用的Cache Abstraction 。 確保在此過程中將Spring Cache包Javadocs標記為書簽。
(注意:對原始帖子進行了少量編輯以提高可讀性)
昨天發布的另一個新功能與我同時嘗試了一些基于注釋的緩存策略。 緩存抽象基本上是從現有項目中獲取約定,并使其成為Spring核心的一部分。
本質上,它引入了一個新接口CacheManager ,可以通過特定的緩存實現來實現。 從那里開始,它添加了一些新的注釋以使方法可緩存。 這是一個使用我以前的posts對象的示例。
package com.jamescarr.example;import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;import javax.annotation.PostConstruct;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;@Repository
public class MemoryMessageRepository implements MessageRepository {private static final Logger LOG =LoggerFactory.getLogger(MemoryMessageRepository.class);private final Map<String, Message> messages = new ConcurrentHashMap<String, Message>();@Cacheable("message")public Message getMessage(String title){LOG.info("Fetching message");return messages.get(title);}@CacheEvict(value="message", key="message.title")public void save(Message message){LOG.info("Saving message");messages.put(message.getTitle(), message);}public Collection<Message> findAll() {return messages.values();}@PostConstructpublic void addSomeDefaultMessages(){save(new Message("Hello", "Hello World"));save(new Message("Appointment", "Remember the milk!"));}}
在這里,您會發現finder方法具有@Cachable批注,其名稱指定了要存儲到的緩存。 它還可以使用其他屬性,例如,使用表達式語言從傳入的參數確定鍵的鍵。默認值為所有方法參數的值。 在保存方法上,我使用@CacheEvict從緩存中刪除已緩存的元素(如果已存在)。
當然,這本身并不會起作用,因此您必須自己啟用它(這很好……您需要做的最后一件事是發現一個生產應用程序,將不需要緩存的內容緩存起來)。 不幸的是,在撰寫本文時,我還沒有發現如何在非xml中執行此操作,因此這是啟用它并使用ehcache作為實現的spring xml文件。
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:cache="http://www.springframework.org/schema/cache"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"><cache:annotation-driven /><bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/><bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="classpath:com/jamescarr/example/ehcache.xml"/></beans>
ehcache配置:
<ehcache><diskStore path="java.io.tmpdir"/><cache name="message"maxElementsInMemory="100"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="true"maxElementsOnDisk="10000000"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"/></ehcache>
最后將其添加到AppConfiguration中,其中包括執行一個簡單的@ImportResource 。
package com.jamescarr.configuration;
import javax.annotation.PostConstruct;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;import com.jamescarr.example.MessagePrinter;@Configuration
@ComponentScan("com.jamescarr.example")
@ImportResource("classpath:com/jamescarr/example/cache-context.xml")
public class AppConfig {@Autowiredprivate MessagePrinter messagePrinter;@PostConstructpublic void doSomething(){messagePrinter.printMessage("Hello");messagePrinter.printMessage("Hello");}public static void main(String[] args) {new AnnotationConfigApplicationContext(AppConfig.class);}
}
在運行此示例時,第一次單擊該方法時應該有一條日志消息,然后第二次則看不到(因為它是從緩存中拉出的。對于為可能只是為了實現該方法的方法實現備忘錄化而言 ,這絕對是很棒的選擇進行一些CPU密集型計算(但是在一組輸入的情況下給出了確切的預期結果)。我為在該領域進行更多工作而感到興奮……我之前已經做過方法級緩存(這很常見),但是無需DIY就可以使用它。
就是這樣。 一個簡單的指南,可幫助您開始使用James Carr的 Spring的Cache抽象 。 別忘了分享!
相關文章:
- 使用Spring AOP進行面向方面的編程
- 帶有Spring和Maven教程的JAX–WS
- 使用Spring使用Java發送電子郵件– GMail SMTP服務器示例
- 使用Spring AspectJ和Maven進行面向方面的編程
翻譯自: https://www.javacodegeeks.com/2011/02/spring-31-cache-abstraction-tutorial.html