Spring自身并没有实现缓存解决方案,但是对缓存管理功能提供了声明式的支持,能够与多种流行的缓存实现进行集成。

Spring Cache是作用在方法上的(不能理解为只注解在方法上),其核心思想是:当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值存放在缓存中,等到下次利用同样的参数调用该方法时将不再执行该方法,而是直接从缓存中获取结果进行返回。所以在使用Spring Cache的时候我们要保证我们的缓存的方法对于相同的方法参数要有相同的返回结果。

 
1.适合和不适合保存到二级缓存的数据

①适合

[1]经常被查询,很少或几乎不修改的
[2]不是特别重要,允许出现偶尔的并发问题
[3]不会被其他应用程序修改的

②不适合

[1]经常被修改
[2]特别重要,不允许出现任何的并发问题,例如:财务数据
[3]有可能被其他应用程序修改
2.Survey项目中适合存入二级缓存的数据

①验证权限时查询的Res对象

Res getResByServletPath(String servletPath);
②参与调查相关方法

EngageService.PageInfo<Survey> getSurveyPage(Integer userId, boolean completed, Integer pageNum);
EngageService.Survey getSurveyDeeply(Integer surveyId);
3.使用Spring提供的缓存抽象机制整合EHCache
①用伪代码展示缓存切面的工作原理
try {
    //1.尝试从缓存中获取数据
    Object value = cacheMap.get(key);
    
    //2.判断value是否为null
    if(value == null){
        //3.实际执行目标方法
        value = 目标对象.目标方法();
        
        //4.将目标方法执行结果存入缓存
        cacheMap.put(key,value);
    }
    
    //5.返回value
    return value;
}catch(Exceptin e){
}
②Spring缓存抽象使用时的注意事项
[1]如果一个方法在输入相同的情况下输出不一定相同,那么不能使用该机制。
int count = userService.getRegistUserCount(boolean active);
[2]目标方法必须每一次都实际被调用,那么不能使用该机制使用了缓存抽象机制后目标方法理论上只会被执行一次
 

Cache Abstraction

4.使用步骤

①创建键生成器类,实现org.springframework.cache.interceptor.KeyGenerator接口

 
  

public class UserKeyGenerator implements KeyGenerator {
//命名方式:类名.方法名.参数名。。。
@Override
public Object generate(Object target, Method method, Object... params) {
//target:目标对象
//method:目标方法
//params:实参数组
StringBuilder bulider = new StringBuilder();
//获取目标对象名字
String name = target.getClass().getName();
bulider.append(".").append(name);
//获取方法的名字
String methodName = method.getName();
bulider.append(".").append(methodName);
//获取所有的参数
if(params!=null && params.length!=0){
for (int i = 0; i < params.length; i++) {
// Object object = params[i];
bulider.append(".").append(params[i]);
}
}
String key = bulider.substring(1);
System.out.println(key);
return key;
} }

2)需要在Spring配置文件中配置对应的bean

   <bean id="userKeyGenerator" class="com.lamsey.survey.Ehcache.UserKeyGenerator"/>
 
②引入EHCache环境

[1]加入jar包
[2]引入EHCache自身的配置文件,同时创建一个具名的缓存区域
  不要使用3.0以上的

<!-- Ehcache依赖 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.3</version>
</dependency>
</dependencies>

③在Spring配置文件中配置缓存抽象对EHCache的整合
         <!-- spring 整合ehcache -->
<!-- 自定义key生成器 -->
<bean id="userKeyGenerator" class="com.lamsey.survey.Ehcache.UserKeyGenerator"/>
<!-- 配置 EhCacheManagerFactoryBean工厂-->
<bean id="ehCacheManagerFactoryBean" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" >
<property name="configLocation" value="classpath:ehcache.xml"></property>
</bean>
<!-- 配置EhCacheCacheManager -->
<bean id="ehCacheCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" >
<property name="cacheManager" ref="ehCacheManagerFactoryBean"></property>
</bean>
<!--切面及切面表达式配置 -->
<aop:config>
<!-- 利用切面表达式找到切面切入点,进行切面编程 -->
<aop:pointcut expression="execution(* *..ResService.getResByServletPath(String))
or execution(* *..AnswerService.getSurveyPage(Integer, boolean, Integer))
or execution(* *..AnswerService.getSurveyDeeply(Integer))
or execution(* *..SurveyService.completedSurvey(Integer))" id="cachePointCut" />
<!-- 承上启下,得到切入点,同时连接处理的方法。对切入点进行处理(cache) -->
     <!-- 缓存切面优先级高于数据库事务切面优先级 -->
<aop:advisor advice-ref="cacheAdvice" pointcut-ref="cachePointCut" order="1"/>
</aop:config>
<!-- 对切入点进行处理,这里表现为缓存 -->
<!-- 这里的自定义key【className.method.param1..paramn】 -->
<cache:advice id="cacheAdvice" cache-manager="ehCacheCacheManager" key-generator="userKeyGenerator">
<!-- 在cache属性中指定缓存区域的名称 -->
<!-- 指定要使用缓存的具体方法,要求必须是缓存切入点覆盖范围内的方法 -->
<cache:caching cache="surveyCache">
<cache:cacheable method=" getResByServletPath" />
<cache:cacheable method="getSurveyDeeply"/>
</cache:caching>
<!-- 使用另外一个有可能被清空数据的缓存区域 -->
<cache:caching cache="surveyCacheEvicable">
<cache:cacheable method="getSurveyPage" />
<!-- 执行updateSurveyCompleted方法时清空当前缓存区域 -->
<!-- 因为调查有可能更新,当更新后就需要进行重新获取参与调查 ,所以清空该缓存-->
<cache:cache-evict method="completedSurvey" all-entries="true" />
</cache:caching>
</cache:advice>

ehcache.xml(从hibernate复制出来)

<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
its value in the running VM. The following properties are translated:
user.home - User's home directory
user.dir - User's current working directory
java.io.tmpdir - Default temp file path -->
<!-- 默认以内存作为缓存,但如果不够,在这里设置一个电脑目录存储 -->
<diskStore path="java.io.tmpdir"/> <!--Default Cache configuration. These will applied to caches programmatically created through
the CacheManager. The following attributes are required for defaultCache: maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit. -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/> <!--Predefined caches. Add your cache configuration settings here.
If you do not have a configuration for your cache a WARNING will be issued when the
CacheManager starts The following attributes are required for defaultCache: name - Sets the name of the cache. This is used to identify the cache. It must be unique.
maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit. --> <!-- Sample cache named sampleCache1
This cache contains a maximum in memory of 10000 elements, and will expire
an element if it is idle for more than 5 minutes and lives for more than
10 minutes. If there are more than 10000 elements it will overflow to the
disk cache, which in this configuration will go to wherever java.io.tmp is
defined on your system. On a standard Linux system this will be /tmp"
-->
<cache name="surveyCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/> <!-- Sample cache named sampleCache2
This cache contains 1000 elements. Elements will always be held in memory.
They are not expired. -->
<cache name="surveyCacheEvicable"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/> --> <!-- Place configuration for your caches following --> </ehcache>

<!-- 缓存切面优先级高于数据库事务切面优先级 -->

  

缓存切面在外层,事务切面在内层

结论:为了减少不必要的事务操作让缓存切面的优先级高于事务切面的优先级。

 
 
流程总结
   
 

7.配置二级缓存
①创建键生成器,实现KeyGenerator接口
②引入EHCache环境
[1]引入EHCache依赖
[2]引入EHCache自身配置文件
[3]在EHCache中创建两个具名的缓存区域
(1)不清空的
(2)可清空的
③在Spring配置文件中配置缓存抽象和EHCache的整合
[1]配置缓存管理器工厂
[2]配置缓存管理器
[3]配置缓存切面的切入点表达式
execution(* *..ResService.getResByServletPath(String)) or
execution(* *..EngageService.getSurveyPage(..)) or
execution(* *..EngageService.getSurveyDeeply(..)) or
execution(* *..SurveyService.updateSurveyCompleted(..))
[4]配置缓存切面的通知:装配缓存管理器、装配键生成器、指定id
引用具体的缓存区域
用cache:cacheable标签指定要缓存数据的方法
用cache:cache-evict标签指定导致缓存清空的方法
[5]用aop:advisor将切入点表达式和缓存通知关联起来
④设置切面优先级让缓存切面优先级高于事务切面

 

使用Spring提供的缓存抽象机制整合EHCache为项目提供二级缓存的更多相关文章

  1. 7.4mybatis整合ehcache(mybatis无法实现分布式缓存必须和其他缓存框架整合)

    <\mybatis\day02\14查询缓存-二级缓存-整合ehcache.av> mybatis的缓存机制(一级缓存二级缓存和刷新缓存)和mybatis整合ehcache-- 这里有做本 ...

  2. Spring源码-IOC部分-循环依赖-用实例证明去掉二级缓存会出现什么问题【7】

    实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...

  3. Hibernate二级缓存简述及基于Spring4,Hibernate5,Ehcache3的二级缓存配置

    Hibernate L2缓存 缓存的分类 L2缓存工作原理 放入二级缓存的数据 Ehcache 依赖 ehcache.xml 常用的memoryStoreEvictionPolicy(缓存算法) eh ...

  4. java框架之SpringBoot(11)-缓存抽象及整合Redis

    Spring缓存抽象 介绍 Spring 从 3.1 版本开始定义了 org.springframework.cache.Cache 和 org.springframework.cache.Cache ...

  5. ssh整合hibernate 使用spring管理hibernate二级缓存,配置hibernate4.0以上二级缓存

    ssh整合hibernate 使用spring管理hibernate二级缓存,配置hibernate4.0以上二级缓存 hibernate  : Hibernate是一个持久层框架,经常访问物理数据库 ...

  6. mybatis的缓存机制(一级缓存二级缓存和刷新缓存)和mybatis整合ehcache

    1.1  什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 一级缓存是SqlSession级别的缓存.在操作数据库时需要构造 s ...

  7. Mybatis整合(Redis、Ehcache)实现二级缓存

    目的: Mybatis整合Ehcache实现二级缓存 Mybatis整合Redis实现二级缓存 Mybatis整合ehcache实现二级缓存 ssm中整合ehcache 在POM中导入相关依赖 < ...

  8. Mybatis学习(五)————— 延迟加载和缓存机制(一级二级缓存)

    一.延迟加载 延迟加载就是懒加载,先去查询主表信息,如果用到从表的数据的话,再去查询从表的信息,也就是如果没用到从表的数据的话,就不查询从表的信息.所以这就是突出了懒这个特点.真是懒啊. Mybati ...

  9. Mybatis(五) 延迟加载和缓存机制(一级二级缓存)

    踏踏实实踏踏实实,开开心心,开心是一天不开心也是一天,路漫漫其修远兮. --WH 一.延迟加载 延迟加载就是懒加载,先去查询主表信息,如果用到从表的数据的话,再去查询从表的信息,也就是如果没用到从表的 ...

随机推荐

  1. 4、爬虫之mongodb

    mongodb 简介 MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的产品 ...

  2. Memcached服务加固方案

    配置访问控制.建议用户不要将服务发布到互联网上而被黑客利用,可以通过ECS安全组规则或IPtables配置访问控制规则.例如,在Linux环境中运行命令,在IPtables中添加此规则只允许192.1 ...

  3. MySql常用命令集Mysql常用命令3

    MYSQL常用命令 有很多朋友虽然安装好了mysql但却不知如何使用它.在这篇文章中我们就从连接 MYSQL.修改密码.增加用户等方面来学习一些MYSQL的常用命令. 有很多朋友虽然安装好了mysql ...

  4. PHP常见面试题汇总(二)

    PHP常见面试题汇总(二)   //第51题:统计一维数组中所有值出现的次数?返回一个数组,其元素的键名是原数组的值;键值是该值在原数组中出现的次数 $array=array(4,5,1,2,3,1, ...

  5. 第一行代码 3-2-2 软件也要拼脸蛋-UI界面-更强大的滚动条- 卡片

    <LinearLayout android:orientation="vertical" android:layout_width="match_parent&qu ...

  6. go标准库的学习-encoding/base64

    参考:https://studygolang.com/pkgdoc 导入方式: import "encoding/base64" base64实现了RFC 4648规定的base6 ...

  7. 从Excel表导入数据到Table

    步骤: 1.写第一行SQL,(本sql对应的是oracle数据库) ="INSERT INTO TD_PROMOTION_RATE VALUES("&A3&&quo ...

  8. 原生js 数组的迭代的方法

    一.原生js Array给我们提供很多了方法.方便我们操作数组.这些方法的参数,都需要传入一个匿名函数,匿名函数中有三个参数,分别含义是:数组中的项.该项的索引.以及数组本身. 1.filter方法: ...

  9. kubernetes集群中对多个pod操作命令

    $ for i in 0 1; do kubectl exec web-$i -- sh -c 'echo hello $(hostname) > /usr/share/nginx/html/i ...

  10. kubespray 容器存储设备 -- rook ceph

    1./root/kubespray/roles/docker/docker-storage/defaults/main.yml  #在用kubespray部署集群是制定docker用什么设备 dock ...