spring緩存

在spring緩存機制中,包括了兩個方面的緩存操做:1.緩存某個方法返回的結果;2.在某個方法執行前或後清空緩存。java

下面寫兩個類來模擬Spring的緩存機制:spring

package com.java.test;

/**
 * 一個簡單的Dao接口,咱們要對這個接口的方法提供緩存的功能
 *
 */
public interface Dao {
    Object select();
    void save(Object obj);
}

package com.sin90lzc.java.test;

import java.util.HashMap;
import java.util.Map;
/**
 * 實現緩存功能,在Spring中,該類能夠看做是Advice
 *
 */
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.java.test;

/**
 * Dao的代理對象,它不單單完成主要的查詢,存儲操做,還實現了緩存
 *
 */
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的本質。express

2.EHCache Spring僅僅是提供了對緩存的支持,但它並無任何的緩存功能的實現,spring使用的是第三方的緩存框架來實現緩存的功能。其中,spring對EHCache提供了很好的支持。下面咱們以EHCache爲例來介紹spring的緩存配置。apache

在介紹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。咱們看一下它的接口定義:app

/*
 * 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接口的定義:less

/*
 * 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的一個實現ide

<!-- 
        該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方式的緩存配置ui

<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.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>
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)");
    }

}
相關文章
相關標籤/搜索