SpringキャッシングとEhcacheの例

Spring CachingとEhcacheの例

spring-ehcache

このチュートリアルでは、Springアプリケーションでデータキャッシュを有効にし、一般的な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

Note
Springはバージョン3.1以降のキャッシュをサポートします
Springキャッシュはバージョン4.1以降大幅に改善されました

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

spring-ehcache-example

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)