直接跳到内容

系统缓存

面对不同缓存框架,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)
系统缓存 has loaded