Spring CachingとEhcacheの例

このチュートリアルでは、Springアプリケーションでデータキャッシュを有効にし、一般的なEhcacheフレームワークと統合する方法を示します。
使用したツール
-
ehcache 2.9
-
Spring 4.1.4.RELEASE
-
ログバック1.0.13
-
Maven 3 / Gradle 2
-
JDK 1.7
-
Eclipse 4.4
Note
Springはバージョン3.1以降のキャッシュをサポートします
Springキャッシュはバージョン4.1以降大幅に改善されました
1. プロジェクトのディレクトリ構造

2. プロジェクトの依存関係
Springキャッシングはspring-context.jarにあり、Ehcacheキャッシングをサポートするには、spring-context-support.jarも含める必要があります。
Mavenプロジェクトの場合:
pom.xml
net.sf.ehcache ehcache 2.9.0 ch.qos.logback logback-classic 1.0.13 org.springframework spring-context 4.1.4.RELEASE org.springframework spring-context-support 4.1.4.RELEASE
Gradleプロジェクトの場合:
gradle.build
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。
Movie.java
package com.example.movie;
import java.io.Serializable;
public class Movie implements Serializable {
int id;
String name;
String directory;
//getters and setters
//constructor with fields
//toString()
}
MovieDao.java
package com.example.movie;
public interface MovieDao{
Movie findByDirector(String name);
}
MovieDaoImpl.java
package com.example.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);
}
}
}
AppConfig.java
package com.example.test;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan({ "com.example.*" })
public class AppConfig {
}
App.java
package com.example.test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.example.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.example.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis] findByDirector is running... 2015-01-22 10:39:06 [main] DEBUG com.example.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis] findByDirector is running... 2015-01-22 10:39:08 [main] DEBUG com.example.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]
findByDirectorを呼び出すたびに、2秒の遅延が発生します。
4. Spring Cachingの例+ EhCache
ここで、メソッドfindByDirectorでデータキャッシュを有効にします。
4.1 Create a ehcache.xml file, to tell Ehcache how and where to cache the data.
src/main/resource/ehcache.xml
Note
Ehcacheの構成方法については、この公式のehcache.xmlの例をお読みください。
4.2 Add @Cacheable on the method you want to cache.
MovieDaoImpl.java
package com.example.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 Enable Caching with @EnableCaching and declared a EhCacheCacheManager.
AppConfig.java
package com.example.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.example.*" })
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 In non-web application, you need to shut down the Spring context manually, so that Ehcache got chance to shut down as well, otherwise Ehcache manager will hang there.
App.java
package com.example.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.example.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.example.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis] 2015-01-22 10:53:28 [main] DEBUG com.example.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis] 2015-01-22 10:53:28 [main] DEBUG com.example.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis] INFO: Shutting down EhCache CacheManager
実行時間を確認します。遅延はありません。 さらに、このメソッドは1回しか実行されず、後続の呼び出しでオブジェクトがキャッシュから取得されるため、「findByDirectorが実行中...」が1つだけ出力されます。
完了しました。
More on Spring Caching
この記事は、Springデータキャッシングの開始を支援し、@CacheEvict、@CachePut、@CacheConfigなどの他のキャッシングアノテーションについて詳しく学ぶことを目的としています。 、この公式のSpring Cache Abstraction documentationを参照してください。詳細については、こちらをご覧ください。
ソースコードをダウンロード
ダウンロード–Spring-Ehcache-Example.zip(20 KB)