Spring缓存机制的理解

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

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

复制代码

1package com.sin90lzc.java.test; 2 3/** 4 * 一个简单的Dao接口,我们要对这个接口的方法提供缓存的功能 5 * @author Tim 6 * 7 */ 8public interface Dao { 9 Object select(); 10 void save(Object obj); 11}

复制代码

复制代码

1package com.sin90lzc.java.test; 2 3import java.util.HashMap; 4import java.util.Map; 5/** 6 * 实现缓存功能,在Spring中,该类可以看作是Advice 7 * @author Tim 8 * 9 */ 10public class Cache { 11 private static final Map<String, Object> cache = new HashMap<String, Object>(); 12 13 /** 14 * 把对象添加到缓存中去 15 * @param key 16 * @param value 17 */ 18 public void checkIn(String key, Object value) { 19 if (!cache.containsKey(key)) { 20 cache.put(key, value); 21 } 22 } 23 24 /** 25 * 从缓存中找对象 26 * @param key 27 * @return 28 */ 29 public Object checkOut(String key) { 30 if (cache.containsKey(key)) { 31 return cache.get(key); 32 } 33 return null; 34 } 35 36 /** 37 * 在方法执行前清除缓存 38 */ 39 public void clearCacheBeforeMethod(){ 40 cache.clear(); 41 } 42 43 /** 44 * 在方法执行后清除缓存 45 */ 46 public void clearCacheAfterMethod(){ 47 cache.clear(); 48 } 49}

复制代码

复制代码

1package com.sin90lzc.java.test; 2 3/** 4 * Dao的代理对象,它不仅仅完成主要的查询,存储操作,还实现了缓存 5 * @author Tim 6 * 7 */ 8public class DaoProxy implements Dao { 9 private Cache cache;//该对象实现了缓存的功能 10 private Dao daoImpl;//完成主要查询,存储操作的Dao实现类,注意,这是一个Dao的实现类 11 12 public Object select() { 13 //在执行方法前,尝试从缓存中取出结果并返回,如果没找到,则执行实际的操作。 14 Object obj = cache.checkOut("DaoProxy.select"); 15 boolean hasCache = false; 16 if (obj != null) { 17 hasCache = true; 18 return obj; 19 } 20 21 //实际的查询操作 22 obj = daoImpl.select(); 23 24 //如果在缓存中找不到该方法的结果,缓存该结果 25 if (!hasCache) { 26 cache.checkIn("DaoProxy.select", obj); 27 } 28 return obj; 29 } 30 31 @Override 32 public void save(Object obj) { 33 //在执行方法前清除缓存 34 cache.clearCacheBeforeMethod(); 35 //实际的操作 36 daoImpl.save(obj); 37 //在执行方法后清除缓存 38 cache.clearCacheAfterMethod(); 39 } 40 41 public void setCache(Cache cache) { 42 this.cache = cache; 43 } 44 45 public void setDao(Dao dao) { 46 this.daoImpl = dao; 47 } 48 49}

复制代码

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

2.EHCache

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

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

复制代码

1<?xml version="1.0" encoding="UTF-8" ?> 2<ehcache> 3 <!-- 定义默认的缓存区,如果在未指定缓存区时,默认使用该缓存区 --> 4 <defaultCache maxElementsInMemory="500" eternal="true" 5 overflowToDisk="false" memoryStoreEvictionPolicy="LFU"> 6 </defaultCache> 7 <!-- 定义名字为"dao.select"的缓存区 --> 8 <cache name="dao.select" maxElementsInMemory="500" eternal="true" 9 overflowToDisk="false" memoryStoreEvictionPolicy="LFU" /> 10</ehcache>

复制代码

3.Spring缓存机制中的Advice

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

复制代码

1/* 2 * Copyright 2002-2011 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package org.springframework.cache; 18 19/** 20 * Interface that defines the common cache operations. 21 * 22 * <b>Note:</b> Due to the generic use of caching, it is recommended that 23 * implementations allow storage of <tt>null</tt> values (for example to 24 * cache methods that return {@code null}). 25 * 26 * @author Costin Leau 27 * @since 3.1 28 */ 29public interface Cache { 30 31 /** 32 * Return the cache name. 33 */ 34 String getName(); 35 36 /** 37 * Return the the underlying native cache provider. 38 */ 39 Object getNativeCache(); 40 41 /** 42 * Return the value to which this cache maps the specified key. Returns 43 * <code>null</code> if the cache contains no mapping for this key. 44 * @param key key whose associated value is to be returned. 45 * @return the value to which this cache maps the specified key, 46 * or <code>null</code> if the cache contains no mapping for this key 47 */ 48 ValueWrapper get(Object key); 49 50 /** 51 * Associate the specified value with the specified key in this cache. 52 * <p>If the cache previously contained a mapping for this key, the old 53 * value is replaced by the specified value. 54 * @param key the key with which the specified value is to be associated 55 * @param value the value to be associated with the specified key 56 */ 57 void put(Object key, Object value); 58 59 /** 60 * Evict the mapping for this key from this cache if it is present. 61 * @param key the key whose mapping is to be removed from the cache 62 */ 63 void evict(Object key); 64 65 /** 66 * Remove all mappings from the cache. 67 */ 68 void clear(); 69 70 71 /** 72 * A (wrapper) object representing a cache value. 73 */ 74 interface ValueWrapper { 75 76 /** 77 * Return the actual value in the cache. 78 */ 79 Object get(); 80 } 81 82}

复制代码

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

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

复制代码

1/* 2 * Copyright 2002-2011 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package org.springframework.cache; 18 19import java.util.Collection; 20 21/** 22 * A manager for a set of {@link Cache}s. 23 * 24 * @author Costin Leau 25 * @since 3.1 26 */ 27public interface CacheManager { 28 29 /** 30 * Return the cache associated with the given name. 31 * @param name cache identifier (must not be {@code null}) 32 * @return associated cache, or {@code null} if none is found 33 */ 34 Cache getCache(String name); 35 36 /** 37 * Return a collection of the caches known by this cache manager. 38 * @return names of caches known by the cache manager. 39 */ 40 Collection<String> getCacheNames(); 41 42}

复制代码

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

复制代码

1  <!-- 2 该Bean是一个org.springframework.cache.CacheManager对象 3 属性cacheManager是一个net.sf.ehcache.CacheManager对象 4 --> 5 <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> 6 <property name="cacheManager"> 7 <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> 8 <property name="configLocation" value="classpath:ehcache-config.xml"></property> 9 </bean> 10 </property> 11 </bean>

复制代码

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

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

复制代码

1<beans xmlns="http://www.springframework.org/schema/beans" 2 xmlns:cache="http://www.springframework.org/schema/cache" 3 xmlns:context="http://www.springframework.org/schema/context" 4 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 7 http://www.springframework.org/schema/context 8 http://www.springframework.org/schema/context/spring-context-3.1.xsd 9 http://www.springframework.org/schema/cache 10 http://www.springframework.org/schema/cache/spring-cache-3.1.xsd 11 http://www.springframework.org/schema/aop 12 http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 13 "> 14 15 <context:component-scan base-package="com.sin90lzc"></context:component-scan> 16 <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> 17 <property name="cacheManager"> 18 <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> 19 <property name="configLocation" value="classpath:ehcache-config.xml"></property> 20 </bean> 21 </property> 22 </bean> 23 24 <cache:advice id="cacheAdvice" cache-manager="cacheManager"> 25 <cache:caching> 26 <cache:cacheable cache="dao.select" method="select" 27 key="#id" /> 28 <cache:cache-evict cache="dao.select" method="save" 29 key="#obj" /> 30 </cache:caching> 31 </cache:advice> 32 33 <aop:config> 34 <aop:advisor advice-ref="cacheAdvice" pointcut="execution(* com.sin90lzc.train.spring_cache.simulation.DaoImpl.*(..))"/> 35 </aop:config> 36</beans>

复制代码

5.注解驱动的缓存配置

复制代码

1<beans xmlns="http://www.springframework.org/schema/beans" 2 xmlns:cache="http://www.springframework.org/schema/cache" 3 xmlns:context="http://www.springframework.org/schema/context" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 7 http://www.springframework.org/schema/context 8 http://www.springframework.org/schema/context/spring-context-3.1.xsd 9 http://www.springframework.org/schema/cache 10 http://www.springframework.org/schema/cache/spring-cache-3.1.xsd"> 11 12 <context:component-scan base-package="com.sin90lzc"></context:component-scan> 13 14 <!-- 15 该Bean是一个org.springframework.cache.CacheManager对象 16 属性cacheManager是一个net.sf.ehcache.CacheManager对象 17 --> 18 <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> 19 <property name="cacheManager"> 20 <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> 21 <property name="configLocation" value="classpath:ehcache-config.xml"></property> 22 </bean> 23 </property> 24 </bean> 25 26 <cache:annotation-driven /> 27 28 29</beans>

复制代码

复制代码

1package com.sin90lzc.train.spring_cache.simulation; 2 3import org.springframework.cache.annotation.CacheEvict; 4import org.springframework.cache.annotation.Cacheable; 5import org.springframework.stereotype.Component; 6 7 8@Component 9public class DaoImpl implements Dao { 10 11 /** 12 * value定义了缓存区(缓存区的名字),每个缓存区可以看作是一个Map对象 13 * key作为该方法结果缓存的唯一标识, 14 */ 15 @Cacheable(value = { "dao.select" },key="#id") 16 @Override 17 public Object select(int id) { 18 System.out.println("do in function select()"); 19 return new Object(); 20 } 21 22 @CacheEvict(value = { "dao.select" }, key="#obj") 23 @Override 24 public void save(Object obj) { 25 System.out.println("do in function save(obj)"); 26 } 27 28}

复制代码

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )