Пример Spring Caching и Ehcache
В этом руководстве мы покажем вам, как включить кэширование данных в приложении Spring и интегрировать его с популярным фреймворкомEhcache.
Используемые инструменты
-
Ehcache 2.9
-
Весна 4.1.4. РЕЛИЗ
-
Logback 1.0.13
-
Maven 3 / Gradle 2
-
JDK 1,7
-
Затмение 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
Просмотрите выполненное время, задержек нет. Кроме того, печатается только один «findByDirector…», поскольку этот метод выполняется только один раз, последующий вызов получит объект из кэша.
Готово.
More on Spring Caching
Эта статья предназначена для того, чтобы помочь вам начать работу с кэшированием данных Spring, чтобы узнать больше о других аннотациях кеширования, таких как@CacheEvict
,@CachePut
,@CacheConfig
и т. д. Пожалуйста, обратитесь к этому официальномуSpring Cache Abstraction documentation, там довольно подробно.
Скачать исходный код
Скачать -Spring-Ehcache-Example.zip (20 КБ)