SPRING CACHE之ConcurrentMapCacheManager改造
ConcurrentMapCacheManager可以作為一種緩存方案,但不能設(shè)置過期,最大緩存條目等,需進行改造。- pom.xml中加入依賴包
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
- 改造CacheManager,MyConcurrentMapCacheManager
package com.paul.common.cache;
/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import com.google.common.cache.CacheBuilder;
/**
* {@link CacheManager} implementation that lazily builds {@link ConcurrentMapCache}
* instances for each {@link #getCache} request. Also supports a 'static' mode where
* the set of cache names is pre-defined through {@link #setCacheNames}, with no
* dynamic creation of further cache regions at runtime.
*
* <p>Note: This is by no means a sophisticated CacheManager; it comes with no
* cache configuration options. However, it may be useful for testing or simple
* caching scenarios. For advanced local caching needs, consider
* {@link org.springframework.cache.guava.GuavaCacheManager} or
* {@link org.springframework.cache.ehcache.EhCacheCacheManager}.
*
* @author Juergen Hoeller
* @since 3.1
* @see ConcurrentMapCache
*/
public class MyConcurrentMapCacheManager implements CacheManager {
private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<String, Cache>(16);
private boolean dynamic = true;
private boolean allowNullValues = true;
private long expireTime = 30;
private long maximumSize = 100;
/**
* Construct a dynamic ConcurrentMapCacheManager,
* lazily creating cache instances as they are being requested.
*/
public MyConcurrentMapCacheManager() {
}
/**
* Construct a static ConcurrentMapCacheManager,
* managing caches for the specified cache names only.
*/
public MyConcurrentMapCacheManager(long expireTime, long maximumSize) {
if(expireTime > 0)
this.expireTime = expireTime;
if(maximumSize > 0)
this.maximumSize = maximumSize;
}
/**
* Specify the set of cache names for this CacheManager's 'static' mode.
* <p>The number of caches and their names will be fixed after a call to this method,
* with no creation of further cache regions at runtime.
* <p>Calling this with a {@code null} collection argument resets the
* mode to 'dynamic', allowing for further creation of caches again.
*/
public void setCacheNames(Collection<String> cacheNames) {
if (cacheNames != null) {
for (String name : cacheNames) {
this.cacheMap.put(name, createConcurrentMapCache(name));
}
this.dynamic = false;
}
else {
this.dynamic = true;
}
}
/**
* Specify whether to accept and convert {@code null} values for all caches
* in this cache manager.
* <p>Default is "true", despite ConcurrentHashMap itself not supporting {@code null}
* values. An internal holder object will be used to store user-level {@code null}s.
* <p>Note: A change of the null-value setting will reset all existing caches,
* if any, to reconfigure them with the new null-value requirement.
*/
public void setAllowNullValues(boolean allowNullValues) {
if (allowNullValues != this.allowNullValues) {
this.allowNullValues = allowNullValues;
// Need to recreate all Cache instances with the new null-value configuration
for (Map.Entry<String, Cache> entry : this.cacheMap.entrySet()) {
entry.setValue(createConcurrentMapCache(entry.getKey()));
}
}
}
/**
* Return whether this cache manager accepts and converts {@code null} values
* for all of its caches.
*/
public boolean isAllowNullValues() {
return this.allowNullValues;
}
@Override
public Collection<String> getCacheNames() {
return Collections.unmodifiableSet(this.cacheMap.keySet());
}
@Override
public Cache getCache(String name) {
Cache cache = this.cacheMap.get(name);
if (cache == null && this.dynamic) {
synchronized (this.cacheMap) {
cache = this.cacheMap.get(name);
if (cache == null) {
cache = createConcurrentMapCache(name);
this.cacheMap.put(name, cache);
}
}
}
return cache;
}
/**
* Create a new ConcurrentMapCache instance for the specified cache name.
* @param name the name of the cache
* @return the ConcurrentMapCache (or a decorator thereof)
*/
protected Cache createConcurrentMapCache(String name) {
//return new ConcurrentMapCache(name, isAllowNullValues());
//此處改用GOOGLE GUAVA的構(gòu)造MANAGER方式
return new ConcurrentMapCache(name,
CacheBuilder.newBuilder()
.expireAfterWrite(this.expireTime, TimeUnit.MINUTES)
.maximumSize(this.maximumSize)
.build()
.asMap(),
isAllowNullValues());
}
}
- 配置想著bean, cache-concurrentmap-applicationcontext.xml<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<cache:annotation-driven />
<!-- <bean id="cacheManager"
class="org.springframework.cache.concurrent.ConcurrentMapCacheManager" >
<property name="cacheNames">
<list>
<value>my-local-cache</value>
</list>
</property>
</bean> -->
<bean id="cacheManager"
class="com.paul.common.cache.MyConcurrentMapCacheManager">
<constructor-arg index="0" value="1" />
<constructor-arg index="1" value="5000" />
</bean>
</beans>
- 通過注釋進行使用
/*
* JBoss, Home of Professional Open Source
* Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual
* contributors by the @authors tag. See the copyright.txt in the
* distribution for a full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.paul.springmvc.data;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.paul.springmvc.model.Member;
@Repository
@Transactional
public class MemberDaoImpl implements MemberDao {
@Autowired
private EntityManager em;
@Cacheable(value = "my-local-cache", key = "#id")
public Member findById(Long id) {
System.out.println("MemberDaoImpl NO CACHE
");
return em.find(Member.class, id);
}
public Member findByEmail(String email) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> criteria = cb.createQuery(Member.class);
Root<Member> member = criteria.from(Member.class);
/*
* Swap criteria statements if you would like to try out type-safe criteria queries, a new
* feature in JPA 2.0 criteria.select(member).orderBy(cb.asc(member.get(Member_.name)));
*/
criteria.select(member).where(cb.equal(member.get("email"), email));
return em.createQuery(criteria).getSingleResult();
}
public List<Member> findAllOrderedByName() {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> criteria = cb.createQuery(Member.class);
Root<Member> member = criteria.from(Member.class);
/*
* Swap criteria statements if you would like to try out type-safe criteria queries, a new
* feature in JPA 2.0 criteria.select(member).orderBy(cb.asc(member.get(Member_.name)));
*/
criteria.select(member).orderBy(cb.asc(member.get("name")));
return em.createQuery(criteria).getResultList();
}
@CacheEvict(value="my-local-cache",allEntries=true,beforeInvocation=true)//清空所有緩存
public void register(Member member) {
em.persist(member);
return;
}
}
posted on 2015-02-25 16:34 paulwong 閱讀(2697) 評論(0) 編輯 收藏 所屬分類: SPRING 、性能優(yōu)化 、緩存