缓存cache介绍

时间:2023-03-08 20:22:02
缓存cache介绍

1.  为何要用缓存、缓存的目的是为了什么?(https://my.oschina.net/u/3378039/blog/2986697
 一个程序的瓶颈在于数据库,内存的速度远远大于硬盘的速度,当我们一次又一次请求数据库或远程服务时会导致大量的时间耗费在数据库操作或远程方法调用上,以致于 程序性能恶化,使用数据缓存可以解决此问题。

下面是常用的缓存管理器以及可用注解方式实现缓存机制的集中类型

缓存cache介绍

2.@Cacheable/@CachePut/@CacheEvict/@Caching介绍(https://blog.csdn.net/wjacketcn/article/details/50945887

具体介绍参见链接。

其中cacheable的源码如下:

 public @interface Cacheable {

     /**
* 设定要使用的cache的名字,必须提前定义好缓存
*/
@AliasFor("cacheNames")
String[] value() default {}; /**
* 同value(),决定要使用那个/些缓存
*/
@AliasFor("value")
String[] cacheNames() default {}; /**
* 使用SpEL表达式来设定缓存的key,如果不设置默认方法上所有参数都会作为key的一部分
*/
String key() default ""; /**
* 用来生成key,与key()不可以共用
*/
String keyGenerator() default ""; /**
* 设定要使用的cacheManager,必须先设置好cacheManager的bean,这是使用该bean的名字
*/
String cacheManager() default ""; /**
* 使用cacheResolver来设定使用的缓存,用法同cacheManager,但是与cacheManager不可以同时使用
*/
String cacheResolver() default ""; /**
* 使用SpEL表达式设定出发缓存的条件,在方法执行前生效
*/
String condition() default ""; /**
* 使用SpEL设置出发缓存的条件,这里是方法执行完生效,所以条件中可以有方法执行后的value
*/
String unless() default ""; /**
* 用于同步的,在缓存失效(过期不存在等各种原因)的时候,如果多个线程同时访问被标注的方法
* 则只允许一个线程通过去执行方法
*/
boolean sync() default false; }

(下图来源于https://www.cnblogs.com/psy-code/p/9537830.html

缓存cache介绍

3.使用guava和caffeine缓存(据说spring5开始已经开始用caffeine替换guava)。

以下图列举集中常用的缓存的性能比较柱状图,来源于(https://blog.csdn.net/qq_35981283/article/details/82354081#commentBox

缓存cache介绍

下面主要以guava和caffeine为例,代码如下:

a.使用guava的情景,代码如下(参考网址https://blog.csdn.net/chinabestchina/article/details/78009220):

application-guava.xml

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<cache:annotation-driven/>
<bean id="cacheManager" class="org.springframework.cache.guava.GuavaCacheManager">
<property name="cacheSpecification" value="concurrencyLevel=4,expireAfterAccess=100s,expireAfterWrite=100s" />
<property name="cacheNames">
<list>
<value>guavaCache</value>
</list>
</property>
</bean>
</beans>
 package com.alice.bean;

 public class Student {
public Integer id;
public String name; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}
 package com.alice.guava;

 import com.alice.bean.Student;

 public interface StudentService {
public Student getStudent(Integer id); public Student updateStudent(Student stu); public void deleteStudent(Integer id); public void deleteAllStudent(); public void myDelete(Integer id);
}
 package com.alice.guava;

 import com.alice.bean.Student;
import org.springframework.aop.framework.AopContext;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; @Service("studentGuavaCache")
public class StudentGuavaCacheImpl implements StudentService { @Cacheable(value = "guavaCache",key="'id_'+#id",condition = "#id<3")
public Student getStudent(Integer id) {
Student stu = new Student();
stu.setId(id);
stu.setName("apple");
return stu;
} @CachePut(value = "guavaCache",key="'id_'+#stu.getId()")
public Student updateStudent(Student stu){
System.out.println("update stu");
return stu;
} @CacheEvict(value = "guavaCache",key="'id_'+#id")
public void deleteStudent(Integer id){ System.out.println("delete student "+id);
} public void myDelete(Integer id){
try {
StudentService ss = (StudentService) AopContext.currentProxy();
ss.deleteStudent(id);
return ;
}catch (Exception e){
e.printStackTrace(); }
this.deleteStudent(id);
} @CacheEvict(value = "guavaCache",allEntries = true)
public void deleteAllStudent(){ System.out.println("delete all student ");
}
}
 package com.alice.guava;

 import com.alice.bean.Student;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.Assert; public class SpringGuavaCacheMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:application-cache.xml","classpath:application-spring.xml","classpath:application-mybatis.xml");
StudentService studentService = (StudentService) ac.getBean("studentGuavaCache"); Integer id =1;
Student stu = studentService.getStudent(id); //新建缓存
stu = studentService.getStudent(id); //从缓存中取 studentService.myDelete(id);
stu = studentService.getStudent(id); //从缓存中取 stu.setName("banana"); //重新设置值
Student stu1 = studentService.getStudent(id);
stu.setName("banana");
studentService.updateStudent(stu); //更新缓存
stu = studentService.getStudent(id); //从缓存中取出新值 stu = new Student(); //新实例
stu.setId(0);
studentService.updateStudent(stu); //用新建的实例进行更新,会新建缓存
stu = studentService.getStudent(0); //从缓存中取 studentService.deleteStudent(id); // 删除缓存
stu = studentService.getStudent(id); //再次新建缓存 id=2;
stu = studentService.getStudent(id); //新建缓存
studentService.deleteAllStudent(); //删除所有缓存
id=1;
stu = studentService.getStudent(id); //因所有缓存被前一步清除,会新建缓存 id=5;
stu = studentService.getStudent(id); //不会新建缓存 因为设置了缓存条件必须小于3
stu = studentService.getStudent(id); //因没有缓存,不会从缓存中取 Assert.notNull(stu,"deprecated");
}
}

2.使用caffeine

这里扩展了下原本的caffeineManager

 package com.alice.caffeine;

 import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.caffeine.CaffeineCacheManager; import java.util.concurrent.TimeUnit; public class CaffeineCacheExtManager extends CaffeineCacheManager { public CaffeineCacheExtManager(){
super();
}
/**
* Construct a CaffeineCacheExtManager managing caches with expireAfterWrite feature
*
* @param duration
* @param timeUnit
*/
public CaffeineCacheExtManager(long duration, String timeUnit) {
this.setCaffeine(Caffeine.newBuilder().expireAfterWrite(duration, TimeUnit.valueOf(timeUnit.toUpperCase())));
} }

application-caffeine.xml

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<cache:annotation-driven/> <bean id="cacheManager" class="org.springframework.cache.caffeine.CaffeineCacheManager"/> <bean id="tenSecondCacheManager" class="com.alice.caffeine.CaffeineCacheExtManager">
<constructor-arg name="duration" value="10"/>
<constructor-arg name="timeUnit" value="SECONDS"/>
</bean>
</beans>
 package com.alice.caffeine;

 import com.alice.bean.Student;

 public interface StudentService {
public Student getStudent(Integer id);
}
 package com.alice.caffeine;

 import com.alice.bean.Student;
import org.springframework.aop.framework.AopContext;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; @Service("CaffeineCache")
public class StudentCaffeineCacheImpl implements StudentService { @Cacheable(cacheManager = CacheMgmtName.TEN_SECOND_CACHE_MANAGER,cacheNames =CacheNames.QUERY_STUINFO_CACHE, key="'id_'+#id",condition = "#id<3")
public Student getStudent(Integer id) {
Student stu = new Student();
stu.setId(id);
stu.setName("apple");
return stu;
}
}
 package com.alice.caffeine;

 import com.alice.bean.Student;
import com.alice.caffeine.StudentService;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class test {
public static void main(String[] args){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:application-cache.xml","classpath:application-spring.xml","classpath:application-mybatis.xml","classpath:application-caffeine.xml");
StudentService studentService = (StudentService) ac.getBean("CaffeineCache");
int id =1;
Student stu = studentService.getStudent(id);
stu = studentService.getStudent(id);
}
}