在本教程中,我们将向您展示如何在Spring应用程序中启用数据缓存,以及如何与流行的Ehcache框架集成。
使用的工具
- 高速缓存2.9
- Spring4.1.4。发布
- 重新登录1.0.13
- Maven 3 / Gradle 2
- JDK 1.7
- Eclipse 4.4
注意
从版本3.1开始,Spring支持缓存
自4.1版以来,Spring缓存得到了显着改善
1.项目目录结构
2.项目依赖
Spring缓存位于spring-context.jar
,要支持Ehcache缓存,还需要包括spring-context-support.jar
。
对于Maven项目:
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.9.0</version>
</dependency>
<!-- Optional, to log stuff -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.13</version>
</dependency>
<!-- Spring caching framework inside this -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<!-- Support for Ehcache and others -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
</project>
对于Gradle项目:
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
version = '1.0'
// Uses JDK 7
sourceCompatibility = 1.7
targetCompatibility = 1.7
// Get dependencies from Maven central repository
repositories {
mavenCentral()
}
//Project dependencies
dependencies {
compile 'org.springframework:spring-context:4.1.4.RELEASE'
compile 'org.springframework:spring-context-support:4.1.4.RELEASE'
compile 'net.sf.ehcache:ehcache:2.9.0'
compile 'ch.qos.logback:logback-classic:1.0.13'
}
3. Spring非缓存示例
一个简单的DAO,可通过导演姓名查找电影。
package com.mkyong.movie;
import java.io.Serializable;
public class Movie implements Serializable {
int id;
String name;
String directory;
//getters and setters
//constructor with fields
//toString()
}
package com.mkyong.movie;
public interface MovieDao{
Movie findByDirector(String name);
}
package com.mkyong.movie;
import org.springframework.stereotype.Repository;
@Repository("movieDao")
public class MovieDaoImpl implements MovieDao{
//each call will delay 2 seconds, simulate the slow query call
public Movie findByDirector(String name) {
slowQuery(2000L);
System.out.println("findByDirector is running...");
return new Movie(1,"Forrest Gump","Robert Zemeckis");
}
private void slowQuery(long seconds){
try {
Thread.sleep(seconds);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}
package com.mkyong.test;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan({ "com.mkyong.*" })
public class AppConfig {
}
package com.mkyong.test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.mkyong.movie.MovieDao;
public class App {
private static final Logger log = LoggerFactory.getLogger(App.class);
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MovieDao obj = (MovieDao) context.getBean("movieDao");
log.debug("Result : {}", obj.findByDirector("dummy"));
log.debug("Result : {}", obj.findByDirector("dummy"));
log.debug("Result : {}", obj.findByDirector("dummy"));
}
}
输出量
findByDirector is running...
2015-01-22 10:39:04 [main] DEBUG com.mkyong.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]
findByDirector is running...
2015-01-22 10:39:06 [main] DEBUG com.mkyong.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]
findByDirector is running...
2015-01-22 10:39:08 [main] DEBUG com.mkyong.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]
每次调用findByDirector
都会花费2秒的延迟。
4. Spring缓存示例+ EhCache
现在,我们将在方法findByDirector
上启用数据缓存。
4.1创建一个ehcache.xml
文件,以告诉Ehcache如何以及在何处缓存数据。
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir" />
<cache name="movieFindCache"
maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="1000"
eternal="false"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="300" timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
</ehcache>
注意
要了解如何配置Ehcache,请阅读此官方ehcache.xml示例。
4.2在要缓存的方法上添加@Cacheable
。
package com.mkyong.movie;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;
@Repository("movieDao")
public class MovieDaoImpl implements MovieDao{
//This "movieFindCache" is delcares in ehcache.xml
@Cacheable(value="movieFindCache", key="#name")
public Movie findByDirector(String name) {
slowQuery(2000L);
System.out.println("findByDirector is running...");
return new Movie(1,"Forrest Gump","Robert Zemeckis");
}
private void slowQuery(long seconds){
try {
Thread.sleep(seconds);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}
4.3使用@EnableCaching
启用缓存并声明EhCacheCacheManager
。
package com.mkyong.test;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
@Configuration
@EnableCaching
@ComponentScan({ "com.mkyong.*" })
public class AppConfig {
@Bean
public CacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}
@Bean
public EhCacheManagerFactoryBean ehCacheCacheManager() {
EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
cmfb.setShared(true);
return cmfb;
}
}
4.4在非Web应用程序中,您需要手动关闭Spring上下文,以便Ehcache也有机会关闭,否则Ehcache管理器将挂在那里。
package com.mkyong.test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.mkyong.movie.MovieDao;
public class App {
private static final Logger log = LoggerFactory.getLogger(App.class);
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MovieDao obj = (MovieDao) context.getBean("movieDao");
log.debug("Result : {}", obj.findByDirector("dummy"));
log.debug("Result : {}", obj.findByDirector("dummy"));
log.debug("Result : {}", obj.findByDirector("dummy"));
//shut down the Spring context.
((ConfigurableApplicationContext)context).close();
}
}
输出量
INFO: Initializing EhCache CacheManager
findByDirector is running...
2015-01-22 10:53:28 [main] DEBUG com.mkyong.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]
2015-01-22 10:53:28 [main] DEBUG com.mkyong.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]
2015-01-22 10:53:28 [main] DEBUG com.mkyong.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]
INFO: Shutting down EhCache CacheManager
查看执行时间,没有延迟。 此外,仅打印一个“ findByDirector正在运行……”,因为此方法仅执行一次,后续调用将从缓存中获取对象。
做完了
有关Spring缓存的更多信息
本文旨在帮助您开始使用Spring数据缓存,以了解更多有关@CacheEvict
,@CachePut
,@CacheConfig
等其他缓存注释的信息,请参考此官方Spring Cache Abstraction文档 ,那里有相当详细的信息。
下载源代码
下载它– Spring-Ehcache-Example.zip (20 KB)
参考文献
翻译自: https://mkyong.com/spring/spring-caching-and-ehcache-example/