Java Spring中引入了对Cache的支持,并通过@Cacheable来完成对某个方法的执行进行缓存。
其核心思想是:在调用缓存方法时,把方法的输入参数作为缓存的key,把方法的输出结构作为缓存的value。
使用时,一般按下面步骤执行:
- 声明程序支持@Caching
- 对具体的方法声明使用缓存
Spring对应的实现非常灵活,很容易支持使用外部的缓存,这里分别以google guava
和ehcache
为例来说明怎么使用
集成google guava
使用时很简单,代码如下:
添加maven依赖
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>18.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.1.7.RELEASE</version> </dependency>
|
声明支持@Caching, 并创建CacheConfig
通过@EnableCache
来声明对@Caching的支持,创建CacheConfig并定义不同的缓存策略,代码如下:
import com.google.common.cache.CacheBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurer; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.guava.GuavaCache; import org.springframework.cache.interceptor.CacheErrorHandler; import org.springframework.cache.interceptor.CacheResolver; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.cache.interceptor.SimpleKeyGenerator; import org.springframework.cache.support.SimpleCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
import java.util.Arrays; import java.util.concurrent.TimeUnit;
@Configuration @EnableCaching public class CacheConfig implements CachingConfigurer {
public final static String CACHE_ONE = "cacheOne"; public final static String CACHE_TWO = "cacheTwo";
private final Logger log = LoggerFactory .getLogger(CacheConfig.class);
@Bean @Override public CacheManager cacheManager() { log.info("Initializing simple Guava Cache manager."); SimpleCacheManager cacheManager = new SimpleCacheManager();
GuavaCache cache1 = new GuavaCache(CACHE_ONE, CacheBuilder.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .build());
GuavaCache cache2 = new GuavaCache(CACHE_TWO, CacheBuilder.newBuilder() .expireAfterWrite(60, TimeUnit.SECONDS) .build());
cacheManager.setCaches(Arrays.asList(cache1,cache2));
return cacheManager; }
@Override public CacheResolver cacheResolver() { return null; }
@Bean @Override public KeyGenerator keyGenerator() { return new SimpleKeyGenerator(); }
@Override public CacheErrorHandler errorHandler() { return null; } }
|
对具体的方法声明使用缓存
如果某一个方法要使用缓存,可以在方法上添加@Cacheable
注解,并指定对应的缓存策略名称,如下:
@Service public class CachedService extends WebServiceGatewaySupport implements CachedService {
@Inject private RestTemplate restTemplate;
@Cacheable(CacheConfig.CACHE_ONE) public String getCached() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<String> reqEntity = new HttpEntity<>("url", headers); return restTemplate.exchange("url", HttpMethod.GET, reqEntity, String.class).getBody(); } }
|
集成ehcache
添加maven依赖
<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.13</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.1.4.RELEASE</version> </dependency>
|
声明程序支持@Caching
通过@EnableCache
来声明对@Caching的支持,创建CacheConfig并定义不同的缓存策略,代码如下:
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.demo.*" }) public class AppConfig { @Bean public CacheManager cacheManager() { return new EhCacheCacheManager(ehCacheCacheManager().getObject()); }
@Bean public EhCacheManagerFactoryBean ehCacheCacheManager() { EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean(); cmfb.setConfigLocation(new ClassPathResource("main/resource/ehcache.xml")); cmfb.setShared(true); return cmfb; } }
|
这里对cache的定义放在了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="cache1" maxEntriesLocalHeap="10000" maxEntriesLocalDisk="1000" eternal="false" diskSpoolBufferSizeMB="20" timeToIdleSeconds="300" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LFU" transactionalMode="off"> <persistence strategy="localTempSwap" /> </cache> </ehcache>
|
对具体的方法声明使用缓存
@Cacheable("cache1") public User getUser(String name) { return null; }
|
关闭ehcache instance
web.xml
中配置对应的listener,应用程序销毁时,同时关闭ehcache实例。
<!-- ehcache 磁盘缓存 监控,持久化恢复 --> <listener> <listener-class>net.sf.ehcache.constructs.web.ShutdownListener</listener-class> </listener>
|
参考文章
google guava
ehcache