paulwong

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

posted on 2015-02-25 16:34 paulwong 阅读(2674) 评论(0)  编辑  收藏 所属分类: SPRING性能优化缓存


只有注册用户登录后才能发表评论。


网站导航: