jetcache源码流程图
2025-09-20 15:59:20 0 举报
jetcache源码流程图
作者其他创作
大纲/内容
直接从已解析过的缓存中获取
AbstractCache#do_PUT
AbstractCache#PUT
当前方法是否在 @EnableMethodCache配置的 basePackages 包下
是否有 @CacheUpdate 或@CacheInvalidate相关注解配置
CachedAnnoConfig
@import
valueEncoder - bean:beanName
parseBeanName(valueEncoder)
DefaultSpringEncoderParser#parseEncoder
获取/创建cache 实例
是执行缓存删除逻辑
通过 CacheManager 获取/创建 Cache 实例
ConfigProvider#parseValueEncoder
@Bean
这个分支我们可以知道,如果你没有通过API 方式创建 Cache 实例,而且也没有 @Cached 注解的方法,那么就创建不了 Cache 实例,也就是用不了 jetcache 了
setAdvice
解析 key 这个 el 表达式得到 key
JetCacheInterceptor
(cacheAnnoConfig instanceof CacheInvalidateAnnoConfig) || (cacheAnnoConfig instanceof CacheUpdateAnnoConfig)如果当前方法是 @CacheInvalidate 或是@CacheUpdate 注解的方法则先尝试从 CacheManager 中获取,如果还没有则再尝试去通过 @Cached 的配置去创建 Cache 实例
cacheConfigMap.getByMethodInfo(key)
eb.setValueEncoder(parseValueEncoder(f.getValue()))
AbstractCache#computeIfAbsentImpl
matchesThis(method.getDeclaringClass())
key 为 null直接执行目标对象方法
beanName为 null则 valueEncoder 必须取JAVA/KRYO/KRYO5
CacheHandler.invoke(context)
获取 cacheKey并从 redis 取值
执行任务
是执行@Cached 相关代理逻辑
Cache 实例未创建则去创建
cacheUpdater.accept(loadedValue)
入口
ConfigSelector
configProvider.newContext(cacheManager).createCacheInvokeContext(cacheConfigMap)
cacheAnnoConfig instanceof CachedAnnoConfig如果当前方法是 @Cached 注解的方法,则直接去创建Cache 实例
parseCacheInvalidates(method)
r.getValue()
ConfigMap
代理对象class 和 method 拼接key
解析 key el 表达式
CommonConfiguration
encoderParser -> DefaultSpringEncoderParser
更新 freshKey 的缓存
getPointcut
applicationContext.getBean(beanName)
如果 CacheManager 中没有则通过 @Cached 注解配置进行创建
key - 1
JetCacheProperties
CacheInvalidateAnnoConfig
是直接取cache 中的
CachePointcut
cacheAnnoConfig.getCache()
是执行 update/invalidate 相关逻辑
CacheUpdateAnnoConfig
否执行 CacheLoader 的 load 方法- 也就是目标对象方法
CacheValueHolder
AbstractCacheAutoInit#afterPropertiesSet
解析 @Cached、@CacheRefresh以及@CachePenetrationProtect 注解的属性添加到 CachedAnnoConfig 对象中
取出 @Cached 相关注解的配置信息
decoder 返回的值
删除缓存
加锁执行 Runnable
JetCacheProxyConfiguration
MethodMatcher#matches
解析 @CacheUpdate 注解
eb.setValueDecoder(parseValueDecoder(f.getValue()))
以 redisson 为例看下 cacheKey 构建和 value decoder
invokeWithInvalidateOrUpdate(context)
根据 @Cached 中的 postCondition 条件来判断是否需要更新缓存,没设置默认是 true,也就是需要更新缓存
new SpringConfigProvider()
从这几个判断可以看出:1. @Cached 执行的优先级高于 @CacheUpdate 和 @CacheInvalidate,即使一起使用,也只会生效 @Cached2. @CacheUpdate 和 @CacheInvalidate 可以一起使用,但是 @CacheInvalidate 的逻辑先执行
invoke
cacheManager.getOrCreateCache(b.build())
是否有 @Cached 相关注解配置对象
Runnable
如果 freshKey 不存在或者 freshTime 已过期则需要重新 load
CacheContext#createCacheByCachedConfig
buildKey 执行后newKey - jetcache-demo:user:cache:id:1
从这里可以看出@Cached、@CacheRefresh以及@CachePenetrationProtect这几个注解可以一起使用
这里重要的是这个创建或取出已创建 Cache 实例的 lambda 表达式
启动周期性的定时任务
doInvoke(context)
invokeWithCached
解析 @CacheInvalidate 注解
不管是 refresh 还是 cache 反正都会走到 AbstractCache
cic.getInvalidateAnnoConfigs() != null
((AbstractExternalCache) concreteCache).buildKey(key)
!globalCacheConfig.isEnableMethodCache()如果 @EnableCache 设置了 false 则代表不走代理直接执行方法
((SerialPolicy) bean).encoder()
这里 GET 的时候还会在 RedissonCache 中拼接一次 keyPrefix,所以最终在 redis 中的 refreshKey -> jetcache-demo:user:cache:id:jetcache-demo:user:cache:id:1_#TS#
cic.getCachedAnnoConfig()
keyConvertorParser-> DefaultSpringKeyConvertorParser
主要是构建一个 RefreshTask
ClassFilter#matches
RedissonCache#do_GET
AbstractCache#do_GET
cache 中存在 key 则取cache返回值如果不存在则调用 loader 获取目标对象方法返回值
parseEnableCache(method)
condition 解析结果为 false直接执行目标对象方法
CachePointcut#matches(Class)
如果通过 area 和 name 没有找到 @Cached配置则会报错否则有的话则直接去创建 Cache 实例
AbstractLifecycle#doInit()
SimpleCacheManager
extends
RefreshCache.RefreshTask#run
AbstractCache#GET
process(\"jetcache.remote.\
@EnableMethodCache
load
注意:方法如果没有解析到 jecache 相关注解的话这里添加的是一个 noCacheInvokeConfigInstance - 代表不匹配
CacheLoader 这个匿名对象中定义了 load 方法 -> 执行目标对象方法
implements
缓存实例已创建则直接获取已创建的
是否有 @CacheUpdate 注解
在包下类名方法名结合生成key
获取/创建cache实例
最终的cacheKey要拼接 keyPrefix + name
解析 @EnableCache注解
process(\"jetcache.local.\
cac == null || cac == CacheInvokeConfig.getNoCacheInvokeConfigInstance()取到的是空或者是noCacheInvokeConfigInstance则表示不需要代理 - 直接执行方法
cp.init()
否直接执行目标对象方法
buildKey(key)
valueDecoder 和 valueEncoder 解析规则是一样的
AutoConfigureBeans
new CacheLoader() {...}
createConfigProvider()
return cache
解析 conditionel 表达式
springboot 整合 jetcache 我就只画以下2部分1. valueEncoder/valueDecoder 解析相关2. jetcache.local/jetcache.remote 解析
springboot整合入口
holder = (CacheValueHolder<V>) valueDecoder.apply(data)
newLoader.apply(key)
否则该 bean是一个 SerialPolicy
缓存中是否有值
DefaultEncoderParser#parseEncoder
执行目标对象方法获取最新的 value
重新 load并更新缓存
ConfigProvider#doInit
是执行缓存更新逻辑
JetCache AOP 的核心配置类
SpringConfigProvider#doInit
fresh 的理解1. fresh 启动线程是在 @Cached 的执行逻辑中的2. @RefreshCache 需要和 @Cached 一起用3. 需要先访问 @Cached 注解的方法才会启动 refresh 定时任务4. 使用 @RefreshCache 且定时任务启动后,redis 中会多一个 freshKey,且这个 freshKey 会多拼一次 keyPrefix
这里再加个分支
当 cache instanceof RefreshCache 时开启 refresh 线程执行定时refresh 的任务
用于注册 AOP BeanPostProcessor
解析 condition el 表达式判断 condition 是否为 true
true更新缓存
RedissonCache#getCacheKey
解析 value el 表达式
以 redisson 为例1. 看下存入 redis 的是什么对象2. cacheKey 构建3. value encoder
invokeOrigin(context)
parseCacheUpdate(method)
为 null 则去解析方法上的 @Cached、@CacheUpdate、@CacheInvalidate 注解信息
设置了 multi 的话就是 removeAll / putAll
cacheConfigMap
更新缓存
@EnableConfigurationProperties
invocation.proceed()
如果 bean instanceof Function
从缓存中取出已经解析好的一些注解配置信息
以redis 这个外部缓存则走的是 externalLoad 逻辑引入的是 jetcache-starter-redisson
GlobalCacheConfig
CacheAnnoConfig
timestampKey - jetcache-demo:user:cache:id:1_#TS#
否
是否有 @CacheInvalidate注解
concreteCache.GET(timestampKey)
外部缓存如 redis 等都会将 value 包装到 CacheValueHolder 中,可以引入别的依赖看看 AbstractExternalCache 下的是不是都是这样的(我这里引入的是 jetcache-starter-redisson 依赖)
name 属性如果没配置那么cacheName 就会默认是 - 类型名拼接方法名
valueEncoder 如果是 bean: 开头的话就可以就获取对应的 bean
l.load(key)
CacheAdvisor
@AutoWired
updateAnnoConfig != null
cache.removeAll(keys)或者cache.remove(key)
parseCached(method)
返回值更新到缓存
AutoProxyRegistrar
SpringConfigProvider
JetCacheAutoConfiguration
0 条评论
下一页