• 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)");
        }
    
    }
    复制代码

  • 相关阅读:
    URAL——DFS找规律——Nudnik Photographer
    URAL1353——DP——Milliard Vasya's Function
    URAL1203——DPor贪心——Scientific Conference
    递推DP HDOJ 5389 Zero Escape
    区间DP UVA 1351 String Compression
    树形DP UVA 1292 Strategic game
    Manacher HDOJ 5371 Hotaru's problem
    同余模定理 HDOJ 5373 The shortest problem
    递推DP HDOJ 5375 Gray code
    最大子序列和 HDOJ 1003 Max Sum
  • 原文地址:https://www.cnblogs.com/liangxinzhi/p/4275565.html
Copyright © 2020-2023  润新知