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

<script type="text/javascript">

<!-- google_ad_client = "ca-pub-1944176156128447";

/* cnblogs 首页横幅 */

google_ad_slot = "5419468456"; google_ad_width = 728; google_ad_height = 90;

//-->

</script>

<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>

转自:http://blog.csdn.net/dyllove98/article/details/8588790

Spring缓存机制的理解的更多相关文章

  1. Spring(五)Spring缓存机制与Redis的结合

    一.Redis和数据库的结合 使用Redis可以优化性能,但是存在Redis的数据和数据库同步的问题. 例如,T1时刻以将 key1 保存数据到 Redis,T2时刻刷新进入数据库,但是T3时刻发生了 ...

  2. Spring缓存机制(转)

    Spring的缓存机制非常灵活,可以对容器中任意Bean或者Bean的方法进行缓存,因此这种缓存机制可以在JavaEE应用的任何层次上进行缓存. Spring缓存底层也是需要借助其他缓存工具来实现,例 ...

  3. spring 缓存机制

    简介 Spring3.1开始引入了基于注释的缓存,其使用方法和原理类似于Spring对事务管理的支持.可以对容器中的任意的bean或bean的方法添加缓存.   配置Spring缓存 Spring缓存 ...

  4. iOS笔记-(缓存机制的理解与实现)

    (1)运行中的现象: 在iOS开发中,会遇到:同一NSURL被多次请求,会造成用户的流量浪费,程序的响应速度不够快.比如说,从服务器上请求一张图片,请求100次,下载的结果都是一样的. (2)解决方法 ...

  5. 手写Spring框架,加深对Spring工作机制的理解!

    在我们的日常工作中,经常会用到Spring.Spring Boot.Spring Cloud.Struts.Mybatis.Hibernate等开源框架,有了这些框架的诞生,平时的开发工作量也是变得越 ...

  6. 8 -- 深入使用Spring -- 5... Spring 3.1 新增的缓存机制

    8.5 Spring 3.1 新增的缓存机制 Spring 3.1 新增了一种全新的缓存机制,这种缓存机制与Spring容器无缝地整合在一起,可以对容器中的任意Bean或Bean的方法增加缓存.Spr ...

  7. spring-boot整合ehcache实现缓存机制

    EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. ehcache提供了多种缓存策略,主要分为内存和磁盘两级,所以无需担心 ...

  8. 以Spring整合EhCache为例从根本上了解Spring缓存这件事(转)

    前两节"Spring缓存抽象"和"基于注解驱动的缓存"是为了更加清晰的了解Spring缓存机制,整合任何一个缓存实现或者叫缓存供应商都应该了解并清楚前两节,如果 ...

  9. Linux 系统缓存机制学习

    前言:本文为参考他人的文章,是一篇学习记录型博客.理解linux的系统缓存机制有助于理解elasticsearch实时更新的原理. 一.缓存机制 为了提高文件系统性能,内核利用一部分物理内存分配出缓冲 ...

随机推荐

  1. HTML5简介

    HTML5简介 HTML5是HTML的最新修订标准.2014年10月29日,万维网联盟(W3C)宣布,经过8年的努力,HTML5标准规范制定完成. HTML5的设计目的是在移动设备上使用多媒体. HT ...

  2. H-1B身份六年后的延期问题

    http://www.hooyou.com/cn_version/h-1b/extension.html H-1B首次获签的在美国居留时限是三年,三年期满后还可以申请延期再续三年,总计在美国的最长时限 ...

  3. 关闭firefox的plugincheck

    每次打开firefox都弹出这个SB页面: https://www.mozilla.org/en-US/plugincheck/ 关不掉, 很是烦人. 经过地番google,找到了答案: about: ...

  4. PHP数组的基础知识

  5. shell笔记

    shell:俗称操作系统的"外壳",就是命令解释程序.     是用户与Linux内核之间的接口.     是负责与用户交互,分析.执行用户输入的命令,并给出结果或出错提示.    ...

  6. PHP HTTP请求

    stream_context_create 1.curl仍然是最好的HTTP库,没有之一. 可以解决任何复杂的应用场景中的HTTP 请求2. 文件流式的HTTP请求比较适合处理简单的HTTP POST ...

  7. querySelectorAll 方法相比 getElementsBy 系列方法区别

    最近有人问到querySelectorAll 方法相比 getElementsBy 系列方法区别,一时没想起来说些什么,今天查下文档,总结一下它们的区别,以便自己理解. 1. W3C 标准queryS ...

  8. json简单使用

    web工程中如何将大量数据从服务器端传送到浏览器一直是很重要的一个问题. 其中一个解决方法是在服务器端将将数据封装成json格式,然后传给前台.废话不多说,下面讲干货. 1.要用json必须下载一个库 ...

  9. app字体被放大效果发虚

    IOS App所有字体被放大,显示效果发虚 小小程序猿 我的博客:http://daycoding.com 分析原因: 由于新版本上线更换了LaunchImage,没有注意美工给的图片尺寸,由于图片尺 ...

  10. 了解JavaScript 数组对象及其方法

    数组在我目前学习过的编程语言中都可以见到, 形形色色的方法也数不胜数, 不过功能都一样, 最多也就是方法名稍稍有所不同, 老外也没个准啊, 如果英语比较好的同学对于学习方法(method)来说是很快的 ...