SPRING CACHE之ConcurrentMapCacheManager改造

SPRING CACHE之ConcurrentMapCacheManager改造

ConcurrentMapCacheManager可以作为一种缓存方案,但不能设置过期,最大缓存条目等,需进行改造。
  1. pom.xml中加入依赖包
             < dependency >
                 < groupId >com.google.guava </ groupId >
                 < artifactId >guava </ artifactId >
                 < version >18.0 </ version >
             </ dependency >

  2. 改造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的构造MANAGER方式
             return  new ConcurrentMapCache(name,
                                            CacheBuilder.newBuilder()
                                                        .expireAfterWrite( this.expireTime, TimeUnit.MINUTES)
                                                        .maximumSize( this.maximumSize)
                                                        .build()
                                                        .asMap(), 
                                            isAllowNullValues());
        }

    }


  3. 配置想着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 >


  4. 通过注释进行使用
    /*
     * 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;
        }
    }

你可能感兴趣的:(SPRING CACHE之ConcurrentMapCacheManager改造)