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)