• Spring缓存机制的理解



    在Spring缓存机制中,包括了两个方面的缓存操作:1.缓存某个方法返回的结果;2.在某个方法执行前或后清空缓存。

    下面写两个类来模拟Spring的缓存机制:

    复制代码
    package com.sin90lzc.java.test;
    
    /**
     * 一个简单的Dao接口,我们要对这个接口的方法提供缓存的功能
     * @author Tim
     *
     */
    public interface Dao {
        Object select();
        void save(Object obj);
    }
    复制代码
    复制代码
    package com.sin90lzc.java.test;
    
    import java.util.HashMap;
    import java.util.Map;
    /**
     * 实现缓存功能,在Spring中,该类可以看作是Advice
     * @author Tim
     *
     */
    public class Cache {
        private static final Map<String, Object> cache = new HashMap<String, Object>();
        
        /**
         * 把对象添加到缓存中去
         * @param key
         * @param value
         */
        public void checkIn(String key, Object value) {
            if (!cache.containsKey(key)) {
                cache.put(key, value);
            }
        }
    
        /**
         * 从缓存中找对象
         * @param key
         * @return
         */
        public Object checkOut(String key) {
            if (cache.containsKey(key)) {
                return cache.get(key);
            }
            return null;
        }
        
        /**
         * 在方法执行前清除缓存
         */
        public void clearCacheBeforeMethod(){
            cache.clear();
        }
        
        /**
         * 在方法执行后清除缓存
         */
        public void clearCacheAfterMethod(){
            cache.clear();
        }
    }
    复制代码
    复制代码
    package com.sin90lzc.java.test;
    
    /**
     * Dao的代理对象,它不仅仅完成主要的查询,存储操作,还实现了缓存
     * @author Tim
     *
     */
    public class DaoProxy implements Dao {
        private Cache cache;//该对象实现了缓存的功能
        private Dao daoImpl;//完成主要查询,存储操作的Dao实现类,注意,这是一个Dao的实现类
    
        public Object select() {
            //在执行方法前,尝试从缓存中取出结果并返回,如果没找到,则执行实际的操作。
            Object obj = cache.checkOut("DaoProxy.select");
            boolean hasCache = false;
            if (obj != null) {
                hasCache = true;
                return obj;
            }
            
            //实际的查询操作
            obj = daoImpl.select();
            
            //如果在缓存中找不到该方法的结果,缓存该结果
            if (!hasCache) {
                cache.checkIn("DaoProxy.select", obj);
            }
            return obj;
        }
    
        @Override
        public void save(Object obj) {
            //在执行方法前清除缓存
            cache.clearCacheBeforeMethod();
            //实际的操作
            daoImpl.save(obj);
            //在执行方法后清除缓存
            cache.clearCacheAfterMethod();
        }
    
        public void setCache(Cache cache) {
            this.cache = cache;
        }
    
        public void setDao(Dao dao) {
            this.daoImpl = dao;
        }
    
    }
    复制代码

    从代码中可以看到,真正完成缓存功能的类是Cache,真正完成Dao(数据的增删查改)功能的类是Dao的实现类,这就是实现了实际业务(Dao)与功能(缓存)的分离。实际的Dao操作与缓存功能是如何结合起来的呢?这就是通过代理对象。我们可以注意到ProxyDao的真正身份也是一个Dao,是它把Dao操作与缓存结合起来的。这三个类恰恰说明了AOP的本质。

    2.EHCache

    Spring仅仅是提供了对缓存的支持,但它并没有任何的缓存功能的实现,spring使用的是第三方的缓存框架来实现缓存的功能。其中,spring对EHCache提供了很好的支持。下面我们以EHCache为例来介绍spring的缓存配置。

    在介绍Spring的缓存配置之前,我们先看一下EHCache是如何配置。

    复制代码
    <?xml version="1.0" encoding="UTF-8" ?>
    <ehcache>
        <!-- 定义默认的缓存区,如果在未指定缓存区时,默认使用该缓存区 -->
        <defaultCache maxElementsInMemory="500" eternal="true"
            overflowToDisk="false" memoryStoreEvictionPolicy="LFU">
        </defaultCache>
        <!-- 定义名字为"dao.select"的缓存区 -->
        <cache name="dao.select" maxElementsInMemory="500" eternal="true"
            overflowToDisk="false" memoryStoreEvictionPolicy="LFU" />
    </ehcache>
    复制代码

    3.Spring缓存机制中的Advice

    由于Spring的缓存机制是基于Spring的AOP,那么在Spring Cache中应该存在着一个Advice。没错,在Spring Cache中的Advice是存在的,它就是org.springframework.cache.Cache。我们看一下它的接口定义:

    复制代码
    /*
     * Copyright 2002-2011 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.
     */
    
    package org.springframework.cache;
    
    /**
     * Interface that defines the common cache operations.
     *
     * <b>Note:</b> Due to the generic use of caching, it is recommended that
     * implementations allow storage of <tt>null</tt> values (for example to
     * cache methods that return {@code null}).
     *
     * @author Costin Leau
     * @since 3.1
     */
    public interface Cache {
    
        /**
         * Return the cache name.
         */
        String getName();
    
        /**
         * Return the the underlying native cache provider.
         */
        Object getNativeCache();
    
        /**
         * Return the value to which this cache maps the specified key. Returns
         * <code>null</code> if the cache contains no mapping for this key.
         * @param key key whose associated value is to be returned.
         * @return the value to which this cache maps the specified key,
         * or <code>null</code> if the cache contains no mapping for this key
         */
        ValueWrapper get(Object key);
    
        /**
         * Associate the specified value with the specified key in this cache.
         * <p>If the cache previously contained a mapping for this key, the old
         * value is replaced by the specified value.
         * @param key the key with which the specified value is to be associated
         * @param value the value to be associated with the specified key
         */
        void put(Object key, Object value);
    
        /**
         * Evict the mapping for this key from this cache if it is present.
         * @param key the key whose mapping is to be removed from the cache
         */
        void evict(Object key);
    
        /**
         * Remove all mappings from the cache.
         */
        void clear();
    
    
        /**
         * A (wrapper) object representing a cache value.
         */
        interface ValueWrapper {
    
            /**
             * Return the actual value in the cache.
             */
            Object get();
        }
    
    }
    复制代码

    evict,put方法就是Advice的功能方法,或者可以这样去理解。

    但spring并不是直接使用org.springframework.cache.Cache,spring把Cache对象交给org.springframework.cache.CacheManager来管理,下面是org.springframework.cache.CacheManager接口的定义:

    复制代码
    /*
     * Copyright 2002-2011 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.
     */
    
    package org.springframework.cache;
    
    import java.util.Collection;
    
    /**
     * A manager for a set of {@link Cache}s.
     *
     * @author Costin Leau
     * @since 3.1
     */
    public interface CacheManager {
    
        /**
         * Return the cache associated with the given name.
         * @param name cache identifier (must not be {@code null})
         * @return associated cache, or {@code null} if none is found
         */
        Cache getCache(String name);
    
        /**
         * Return a collection of the caches known by this cache manager.
         * @return names of caches known by the cache manager.
         */
        Collection<String> getCacheNames();
    
    }
    复制代码

    在spring对EHCache的支持中,org.springframework.cache.ehcache.EhCacheManager就是org.springframework.cache.CacheManager的一个实现

    复制代码
      <!-- 
            该Bean是一个org.springframework.cache.CacheManager对象
            属性cacheManager是一个net.sf.ehcache.CacheManager对象
         -->
        <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
            <property name="cacheManager">
                <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
                    <property name="configLocation" value="classpath:ehcache-config.xml"></property>
                </bean>
            </property>
        </bean>
    复制代码

     

    4.基于xml配置方式配置缓存

    在上一节中,我们得到了cacheManagr,那么我们就可以对某些方法配置缓存了。下面是基于xml方式的缓存配置

    复制代码
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:cache="http://www.springframework.org/schema/cache"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.1.xsd
         http://www.springframework.org/schema/cache
         http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
         ">
    
        <context:component-scan base-package="com.sin90lzc"></context:component-scan>
        <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
            <property name="cacheManager">
                <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
                    <property name="configLocation" value="classpath:ehcache-config.xml"></property>
                </bean>
            </property>
        </bean>
    
        <cache:advice id="cacheAdvice" cache-manager="cacheManager">
            <cache:caching>
                <cache:cacheable cache="dao.select" method="select"
                    key="#id" />
                <cache:cache-evict cache="dao.select" method="save"
                    key="#obj" />
            </cache:caching>
        </cache:advice>
    
        <aop:config>
            <aop:advisor advice-ref="cacheAdvice" pointcut="execution(* com.sin90lzc.train.spring_cache.simulation.DaoImpl.*(..))"/>
        </aop:config>
    </beans>
    复制代码

     

    5.注解驱动的缓存配置

    复制代码
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:cache="http://www.springframework.org/schema/cache"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.1.xsd
         http://www.springframework.org/schema/cache
         http://www.springframework.org/schema/cache/spring-cache-3.1.xsd">
    
        <context:component-scan base-package="com.sin90lzc"></context:component-scan>
    
        <!-- 
            该Bean是一个org.springframework.cache.CacheManager对象
            属性cacheManager是一个net.sf.ehcache.CacheManager对象
         -->
        <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
            <property name="cacheManager">
                <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
                    <property name="configLocation" value="classpath:ehcache-config.xml"></property>
                </bean>
            </property>
        </bean>
        
        <cache:annotation-driven />
    
    
    </beans>
    复制代码
    复制代码
    package com.sin90lzc.train.spring_cache.simulation;
    
    import org.springframework.cache.annotation.CacheEvict;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.stereotype.Component;
    
    
    @Component
    public class DaoImpl implements Dao {
    
        /**
         * value定义了缓存区(缓存区的名字),每个缓存区可以看作是一个Map对象
         * key作为该方法结果缓存的唯一标识,
         */
        @Cacheable(value = { "dao.select" },key="#id")
        @Override
        public Object select(int id) {
            System.out.println("do in function select()");
            return new Object();
        }
    
        @CacheEvict(value = { "dao.select" }, key="#obj")
        @Override
        public void save(Object obj) {
            System.out.println("do in function save(obj)");
        }
    
    }
    复制代码

  • 相关阅读:
    quick-cocos2d-x游戏开发【5】——创建菜单
    cocos2d-x3.0 lua学习(一个)
    hdu 3001 Travelling (TSP问题 )
    朱重组成功,?(行家都知道,几乎回答)
    无人机DLG生产作业流程
    自己定制个人无人机需要的准备工作的内容
    C# 多线程网络爬虫
    [转] c#中 多线程访问winform控件
    C# WinForm中 让控件全屏显示的实现代码
    5.数据绑定和表单标签库
  • 原文地址:https://www.cnblogs.com/liangxinzhi/p/4275565.html
Copyright © 2020-2023  润新知