spring-ehcache、width = 322、height = 100

このチュートリアルでは、Springアプリケーションでデータキャッシュを有効にし、一般的なhttp://ehcache.org/[Ehcache]フレームワークと統合する方法を説明します。

使用されるツール

  1. Ehcache 2.9

  2. Spring 4.1.4.RELEASE

  3. ログバック1.0.13

  4. Maven 3/Gradle 2

  5. JDK 1.7

  6. Eclipse 4.4

1.プロジェクトのディレクトリ構造


spring-ehcache-example、width = 628、height = 486

プロジェクトの依存関係

Springキャッシングは

spring-context.jar`にあり、Ehcacheキャッシングをサポートするために

spring-context-support.jar`も含める必要があります。

Mavenプロジェクトの場合:

pom.xml

    <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プロジェクトの場合:

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.mkyong.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.mkyong.movie;

public interface MovieDao{

    Movie findByDirector(String name);

}

MovieDaoImpl.java

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);
            }
    }

}

AppConfig.java

package com.mkyong.test;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan({ "com.mkyong.** " })
public class AppConfig {
}

App.java

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にデータのキャッシュ方法と場所を伝えます。

src/main/resource/ehcache.xml

<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>

**  Note **  + Ehcacheの設定方法については、公式のhttp://ehcache.org/ehcache.xml[ehcache.xml]の例を参照してください。

4.2キャッシュするメソッドに `@ Cacheable`を追加します。

MovieDaoImpl.java

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`を宣言しました。

AppConfig.java

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マネージャがハングします。

App.java

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が実行されているのは1つだけです。

完了しました。

**  Spring Cacheの詳細** この記事は、Springデータキャッシングを始め、 `@ CacheEvict`、` @ CachePut`、 `@ CacheConfig`などの他のキャッシングアノテーションの詳細を学ぶのに役立ちます。この公式http ://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html[Spring Cache Abstractionのドキュメント]、かなり詳細です。

=== ソースコードをダウンロードする

ダウンロードする -  link://wp-content/uploads/2015/01/Spring-Ehcache-Example.zip[Spring-Ehcache-Example.zip](20 KB)

=== 参考文献

.  http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html[Spring

キャッシュ抽象化]。リンク://ehcache/ehcache-hello-world-example/[Ehcache Hello World

例]。 http://ehcache.org/ehcache.xml[ehcache.xmlの例]

.  link://spring3/spring-3-javaconfig-example/[Spring 3 Javaの設定

例]

link://tag/ehcache/[ehcache]link://タグ/spring/[spring]