Spring Caching and Ehcache example

转载:Spring Caching and Ehcache example

不过把ehcahce.xml中的updateCheck=true 改为 false

pom.xml中的log 的dependency 改为:

<!-- Optional, to log stuff -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.5</version>
    </dependency>

然后加上log4j.properties方便看log 输出:

log4j.rootLogger=debug,console 

log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c:%L - %m%n
 

In this tutorial, we will show you how to enable data caching in a Spring application, and integrate with the popular Ehcache framework.

Tools used

  1. Ehcache 2.9
  2. Spring 4.1.4.RELEASE
  3. Logback 1.0.13
  4. Maven 3 / Gradle 2
  5. JDK 1.7
  6. Eclipse 4.4
Note
Spring supports caching since version 3.1
Spring cache has been significantly improved since version 4.1

1. Project Directory Structure

spring-ehcache-example
<iframe id="aswift_1" style="margin: 0px; padding: 0px; border-width: 0px; outline: 0px; vertical-align: baseline; max-width: 100%; left: 0px; position: absolute; top: 0px; background: transparent;" name="aswift_1" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="728" height="90"></iframe>

2. Project Dependencies

The Spring caching is in the spring-context.jar, to support Ehcache caching, you need to include thespring-context-support.jar as well.

For Maven project :

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>

For Gradle project :

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'
}
<iframe id="aswift_2" style="margin: 0px; padding: 0px; border-width: 0px; outline: 0px; vertical-align: baseline; max-width: 100%; left: 0px; position: absolute; top: 0px; background: transparent;" name="aswift_2" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="728" height="90"></iframe>

3. Spring Non-Cache Example

A simple DAO to find a movie by director name.

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

Output

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]

Each call to findByDirector will take 2 seconds delay.

4. Spring Caching Example + EhCache

Now, we will enable data caching on method findByDirector.

4.1 Create a ehcache.xml file, to tell Ehcache how and where to cache the data.

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
To learn how to configure Ehcache, read this official  ehcache.xml example.

4.2 Add @Cacheable on the method you want to cache.

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 Enable Caching with @EnableCaching and declared a 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 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.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();
 
	}
}

Output

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

Review the executed time, there is no delay. In addition, only one “findByDirector is running…” is printed, because this method only executed once, subsequent call will get the object from cache.

Done.

More on Spring Caching
This article is to help you get started with Spring data caching, to learn more about other caching annotations like  @CacheEvict@CachePut@CacheConfig and etc, please refer to this official Spring Cache Abstraction documentation, quite detail over there.

 

猜你喜欢

转载自dreamoftch.iteye.com/blog/2208349