外观
系统缓存
面对不同缓存框架,AgileBPM在其之上做了接口封装,应用层只与封装接口交互,而不关注具体缓存框架实现。
缓存区域
用来指定缓存的过期时间和大小
配置文件:application.yml
ab:
cache:
region:
# 区域名称:过期时间(参考语法:java.time.Duration#parse), 缓存大小(可省略)
SYS_PROPERTIES: PT1H,100
INFO
缓存大小只支持j2cache、内存缓存
缓存接口
com.dstz.base.common.cache.ICache
V getIfPresent(String region, String key)
获取缓存, 如果缓存不存在返回null
参数
- region: 缓存区域
- key:缓存键
V get(String region, String key, Callable<V> loader)
获取缓存,如果缓存不存在则调用loader加载
参数
- region:缓存区域
- key:缓存键
- loader: 加载器
void put(String region, String key, Object value)
放置缓存
参数
- region:缓存区域
- key:缓存键
- value:缓存值
void invalidate(String region, String ...key)
指定缓存键失效
参数
- region:缓存区域
- key:缓存键
void invalidateRegion(String region)
指定缓存区域失效
参数
- region:缓存区域
void invalidateAll()
所有缓存失效
boolean exists(String region, String key)
指定缓存键是否存在
参数
- region:缓存区域
- key:缓存键
切换缓存
AgileBPM提供了三种内置缓存实现
- 内存缓存
- Redis
- J2Cache
memory
配置文件:application.yml
ab:
cache:
type: memory
redis
程序入口模块引入Maven依赖
<dependency>
<groupId>com.dstz</groupId>
<artifactId>ab-component-redis</artifactId>
<version>${project.version}</version>
</dependency>
配置文件:application.yml
spring:
redis:
host:
port:
password:
database:
ab:
cache:
type: redis
j2cache
j2cache是OSChina(开源中国)目前正在使用的两级缓存框架
j2cache 两级缓存结构:
- L1:进程内缓存(caffeine)
- L2:集中式缓存(redis)
程序入口模块引入依赖
<dependency>
<groupId>com.dstz</groupId>
<artifactId>ab-component-j2cache</artifactId>
<version>${project.version}</version>
</dependency>
配置文件:application.yml
ab:
cache:
type: j2cache
j2cache:
level2:
# 二级缓存开启,需联动配置spring redis
cache-open: false
broadcast:
# 开启广播通知
open: ${j2cache.level2.cache-open}
开始使用
使用方式有两种,编码和注解
编码使用
package com.dstz;
import com.dstz.base.common.cache.ICache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Scratch {
/**
* 注入缓存接口
*/
@Autowired
private ICache cache;
public void test() {
// 放入缓存
cache.put("SYS_PROPERTIES", "xxx", "xxx");
// 获取缓存
cache.getIfPresent("SYS_PROPERTIES", "xxx");
// 利用加载器获取缓存
cache.get("SYS_PROPERTIES", "xxx", () -> "xxx");
// 缓存是否存在
cache.exists("SYS_PROPERTIES", "xxx");
// 缓存失效
cache.invalidate("SYS_PROPERTIES", "xxx");
}
}
注解使用
为了简化缓存编码操作,ICache与Spring缓存做了整合,用缓存注解实现方法结果缓存。
@Cacheable
- value/cacheNames
缓存区域
- key
SpEL表达式,缓存KEY;示例:’user:’.concat(#root.args[0])
名称 | 描述 | 示例 |
---|---|---|
methodName | 当前方法名称 | #root.methodName |
method | 当前方法对象 | #root.method.name |
target | 当前被调用对象 | #root.target |
targetClass | 当前被调用对象的Class | #root.targetClass |
args | 当前方法参数组成的数组 | #root.args[0] |
caches | 当前被使用的缓存集合 | #root.caches[0].name |
参数名称 | 方法参数的名字,可以直接 #参数名或者使用 #p0或#a0 的 形式, 0代表参数的索引; | #iban, #a0, #p0, #p<#arg> |
result | 方法执行完成的返回值(仅当方法执行之后的判断有效,如 unless , beforeInvocation=false ) | #result |
- unless
用于否决缓存的,和condition不同,condition是在方法开始之前判断,而该属性是在方法执行完成之后判断;所以condition不能通过方法返回值来判断,而unless属性可以;方法返回值是通过元数据result来表示的,true时表示不会缓存,为false时表示进行缓存;
- sync
表示是否异步,默认为false,也就是同步;一般情况下,Spring的Cache的缓存过期之后,这时候如果多个线程同时对某个数据进行访问,会同时去访问数据库,有可能导致数据库的压力顿时增大,所以Spring4.3之后引入了sync注解,当设置它为true时,会将缓存锁定,只有一个线程的请求会去访问数据库,其他线程都会等待直到缓存可用,这个设置可以减少对数据库的瞬间并发访问;
INFO
注意,不支持unless;实际上该属性只是一个提示或建议,至于是否支持要看我们的cache provider ;
@CacheEvict
该注解用于缓存的清除,注解参数上与@Cacheable大部分相同
- allEntries
是否清空所有的缓存内容,默认为false,如果指定为 true,则方法调用后将清空所有缓存;不过不允许在该值设置为true的情况下,再设置key的值
- beforeInvocation
是否在调用该方法之前清空缓存,默认为false;如果为true,在该方法被调用前就清空缓存,不用考虑该方法的执行结果(即不考虑是否抛出异常);而默认情况下,如果方法执行时发生异常,则不会清除缓存;
示例
@Cacheable(cacheNames="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@Cacheable(cacheNames="books", key="#isbn.rawNumber")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@Cacheable(cacheNames="books", key="T(someType).hash(#isbn)")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result.hardback")
public Book findBook(String name)
@CacheEvict(cacheNames="books", allEntries=true)
public void loadBooks(InputStream batch)