Skip to content

Spring 集成 API ​

CoCache 通过 cocache-spring、cocache-spring-cache 和 cocache-spring-boot-starter 模块与 Spring Framework 提供深度集成。本页面记录所有 Spring 特定的组件。

模块概览 ​

mermaid
graph TB
    subgraph Starter["cocache-spring-boot-starter"]
        style Starter fill:#161b22,stroke:#6d5dfc,color:#e6edf3
        Auto["CoCacheAutoConfiguration"]
        Props["CoCacheProperties"]
        Cond["@ConditionalOnCoCacheEnabled"]
        EP["CoCacheEndpoint"]
        CEP["CoCacheClientEndpoint"]
        EPAC["CoCacheEndpointAutoConfiguration"]
    end

    subgraph SpringCache["cocache-spring-cache"]
        style SpringCache fill:#161b22,stroke:#6d5dfc,color:#e6edf3
        CCM["CoCacheManager"]
        CSC["CoSpringCache"]
    end

    subgraph Spring["cocache-spring"]
        style Spring fill:#161b22,stroke:#6d5dfc,color:#e6edf3
        EC["EnableCoCache"]
        REG["EnableCoCacheRegistrar"]
        SCF["SpringCacheFactory"]
        ACF["AbstractCacheFactory"]
        CPFB["CacheProxyFactoryBean"]
        JCPFB["JoinCacheProxyFactoryBean"]
        SCSC["SpringClientSideCacheFactory"]
        SKCF["SpringKeyConverterFactory"]
        SCSrcF["SpringCacheSourceFactory"]
        SJKEF["SpringJoinKeyExtractorFactory"]
    end

    subgraph Core["cocache-core"]
        style Core fill:#161b22,stroke:#6d5dfc,color:#e6edf3
        CPF["DefaultCacheProxyFactory"]
        CCF["DefaultCoherentCacheFactory"]
    end

    Auto --> SCF
    Auto --> CPF
    Auto --> CCF
    Auto --> CCM
    REG --> CPFB
    REG --> JCPFB
    CPFB --> CPF
    JCPFB --> JCPF["JoinCacheProxyFactory"]
    CCM --> CSC
    SCF --> ACF
    SCSC --> ACF
    SKCF --> ACF
    SCSrcF --> ACF

Factory Bean ​

CacheProxyFactoryBean ​

为 @CoCache 注解的接口创建基于代理的缓存实例的 Spring FactoryBean。

方面详情源码
实现FactoryBean<Cache<Any, Any>>、ApplicationContextAware--
构造函数(cacheMetadata: CoCacheMetadata)--
源文件--CacheProxyFactoryBean.kt:23
方法返回值说明
getObject()Cache<Any, Any>从应用上下文获取 CacheProxyFactory 并调用 create(cacheMetadata)
getObjectType()Class<*>返回缓存接口类(cacheMetadata.proxyInterface.java)

JoinCacheProxyFactoryBean ​

为 @JoinCacheable 注解的接口创建基于代理的 Join 缓存实例的 Spring FactoryBean。

方面详情源码
实现FactoryBean<JoinCache<Any, Any, Any, Any>>、ApplicationContextAware--
构造函数(cacheMetadata: JoinCacheMetadata)--
源文件--JoinCacheProxyFactoryBean.kt:23
方法返回值说明
getObject()JoinCache<Any, Any, Any, Any>从应用上下文获取 JoinCacheProxyFactory 并调用 create(cacheMetadata)
getObjectType()Class<*>返回 Join 缓存接口类

AbstractCacheFactory 模式 ​

AbstractCacheFactory 提供了模板方法模式,用于从 Spring Bean 创建缓存组件,采用按名称优先查找策略和按类型回退机制。

方面详情源码
包me.ahoo.cache.spring--
源文件--AbstractCacheFactory.kt:21

Bean 解析策略 ​

mermaid
flowchart TB
    subgraph Strategy["Bean 解析策略"]
        style Strategy fill:#161b22,stroke:#6d5dfc,color:#e6edf3
        Start["resolve(cacheMetadata)"]
        NameLookup["按名称查找:<br>{cacheName}{suffix}"]
        NameFound{"找到 Bean?"}
        TypeLookup["resolveByType()<br>(仅 CacheSource)"]
        TypeFound{"唯一 Bean?"}
        Fallback["使用默认回退"]
        Return["返回 Bean"]

        Start --> NameLookup
        NameLookup --> NameFound
        NameFound -- "是" --> Return
        NameFound -- "否" --> TypeLookup
        TypeLookup --> TypeFound
        TypeFound -- "是" --> Return
        TypeFound -- "否" --> Fallback
        Fallback --> Return
    end

抽象方法 ​

方法签名说明
suffixabstract val suffix: String此工厂类型的 Bean 名称后缀
resolveByTypeopen fun resolveByType(cacheMetadata: CoCacheMetadata): Any?可选的唯一类型查找(仅用于无状态组件,默认 null)
fallbackabstract fun fallback(cacheMetadata: CoCacheMetadata): Any未找到 Spring Bean 时的默认组件

Spring 工厂实现 ​

所有 Spring 工厂实现都继承 AbstractCacheFactory:先按名称,再(仅无状态组件)按唯一类型,最后使用默认实现。

SpringClientSideCacheFactory ​

方面详情源码
实现ClientSideCacheFactory、AbstractCacheFactory--
Bean 名称后缀.ClientSideCache--
回退DefaultClientSideCacheFactory.create()(按 @CaffeineCache 构建有界 Caffeine)--
源文件--SpringClientSideCacheFactory.kt:25

SpringKeyConverterFactory ​

方面详情源码
实现KeyConverterFactory、AbstractCacheFactory--
Bean 名称后缀.KeyConverter--
回退设置 keyExpression 时使用 ExpKeyConverter,否则使用带计算前缀的 ToStringKeyConverter--
源文件--SpringKeyConverterFactory.kt:27

key 前缀与表达式会解析 Spring 占位符(${...})。转换器从不按类型共享,否则 key 类型相同的两个缓存会共用一个前缀而导致冲突。

SpringCacheSourceFactory ​

方面详情源码
实现CacheSourceFactory、AbstractCacheFactory--
Bean 名称后缀.CacheSource--
回退CacheSource.noOp()--
源文件--SpringCacheSourceFactory.kt:24

SpringJoinKeyExtractorFactory ​

方面详情源码
实现JoinKeyExtractorFactory--
Bean 名称后缀.JoinKeyExtractor--
回退设置 joinKeyExpression 时使用 SpEL,否则按类型查找 Bean--
源文件--SpringJoinKeyExtractorFactory.kt:24

SpringCacheFactory ​

从 Spring BeanFactory 获取缓存 Bean 的 CacheFactory 实现。

方面详情源码
实现CacheFactory--
构造函数(beanFactory: ListableBeanFactory)--
源文件--SpringCacheFactory.kt:24
方法说明
caches通过 getBeansOfType(Cache::class.java) 从应用上下文返回所有 Cache Bean
getCache(cacheName, cacheType)按名称和类型获取缓存 Bean
getCache(keyType, valueType)使用 ResolvableType 按泛型键/值类型获取缓存 Bean

Bean 命名约定 ​

CoCache 使用一致的 {cacheName}.{Suffix} 命名模式用于可选的自定义 Bean。注册具有匹配名称的 Spring Bean 即可覆盖默认行为。

Bean 名称模式工厂用途默认行为
{cacheName}.ClientSideCacheSpringClientSideCacheFactoryL2 本地缓存DefaultClientSideCacheFactory.create()
{cacheName}.DistributedCacheRedisDistributedCacheFactoryL1 分布式缓存基于 Redis 的 RedisDistributedCache
{cacheName}.CacheSourceSpringCacheSourceFactoryL0 数据源CacheSource.noOp()
{cacheName}.KeyConverterSpringKeyConverterFactory键转换ToStringKeyConverter 或 ExpKeyConverter
{cacheName}.JoinKeyExtractorSpringJoinKeyExtractorFactoryJoin 键提取SpEL 表达式或按类型 Bean
{cacheName}.CacheMetadataEnableCoCacheRegistrar解析的注解元数据自动生成

自定义示例 ​

为特定缓存提供自定义 ClientSideCache:

kotlin
@Configuration
class CustomCacheConfig {

    @Bean("user-cache.ClientSideCache")
    fun userClientSideCache(): ClientSideCache<User> {
        return CaffeineClientSideCache.build(maximumSize = 20_000, expireAfterAccess = Duration.ofMinutes(10))
    }

    @Bean("user-cache.CacheSource")
    fun userCacheSource(userRepository: UserRepository): CacheSource<String, User> {
        return CacheSource { key ->
            userRepository.findById(key).map { CacheValue.of(it, TtlAt.at(3600)) }.orElse(null)
        }
    }
}

CoCacheManager ​

CoCache 与 Spring 的 CacheManager 抽象之间的桥接,支持 @Cacheable 和其他 Spring Cache 注解。

方面详情源码
继承AbstractCacheManager--
构造函数(cacheFactory: CacheFactory)--
源文件--CoCacheManager.kt:21
方法返回值说明
loadCaches()Collection<SpringCache>将所有已注册的 CoCache 实例包装为 CoSpringCache 适配器
getMissingCache(name)SpringCache?按名称查找 CoCache 并在找到时包装;否则返回 null

CoCacheManager 流程 ​

mermaid
sequenceDiagram
autonumber
    participant SC as Spring 容器
    participant CCM as CoCacheManager
    participant CF as CacheFactory
    participant CSW as CoSpringCache

    SC->>CCM: getCache("user-cache")
    CCM->>CCM: 检查内部缓存映射
    alt 内部未找到缓存
        CCM->>CF: getCache("user-cache")
        CF-->>CCM: Cache 实例
        CCM->>CSW: new CoSpringCache("user-cache", cache)
        CCM->>CCM: 注册到内部映射
    end
    CCM-->>SC: CoSpringCache 包装器

CoSpringCache ​

将 CoCache 的 Cache 实例适配为 Spring Cache 实现的适配器。

方面详情源码
实现NamedCache、SpringCache、CacheDelegated<Cache<Any, Any?>>--
构造函数(cacheName: String, delegate: Cache<Any, Any?>, asyncExecutor: Executor)--
源文件--CoSpringCache.kt:27
方法Spring 接口说明
getName()Cache.getName()返回缓存名称
getNativeCache()Cache.getNativeCache()返回底层 CoCache 实例
get(key)Cache.get(key)命中时返回 SimpleValueWrapper(value);不存在、已过期或负缓存返回 null
get(key, type)Cache.get(key, type)返回转换为指定类型的值
get(key, valueLoader)Cache.get(key, valueLoader)同一 key 并发时最多加载一次(@Cacheable(sync = true)),然后存储
put(key, value)Cache.put(key, value)委托给 delegate.set(key, value)
evict(key)Cache.evict(key)委托给 delegate.evict(key)
clear()Cache.clear()清除 ClientSideCache(如果是 CoherentCache,仅清除 L2)
retrieve(key)Cache.retrieve(key)在专用 asyncExecutor 上异步查找(不使用 ForkJoin 公共池)
retrieve(key, valueLoader)Cache.retrieve(key, valueLoader)使用 CompletableFuture 组合的异步获取

配合 @Cacheable 使用 ​

注册 CoCacheManager 后,标准 Spring Cache 注解即可无缝工作:

kotlin
@Service
class UserService(
    private val userRepository: UserRepository
) {
    @Cacheable(cacheNames = ["user-cache"], key = "#userId")
    fun getUser(userId: String): User {
        return userRepository.findById(userId).orElseThrow()
    }

    @CacheEvict(cacheNames = ["user-cache"], key = "#userId")
    fun deleteUser(userId: String) {
        userRepository.deleteById(userId)
    }
}

EnableCoCacheRegistrar ​

处理 @EnableCoCache 并注册 CacheProxyFactoryBean/JoinCacheProxyFactoryBean 定义的注册器。

方面详情源码
实现ImportBeanDefinitionRegistrar--
源文件--EnableCoCacheRegistrar.kt:31

注册逻辑 ​

步骤操作
1从 @EnableCoCache.caches 属性解析缓存类型
2拆分为标准缓存(不继承 JoinCache)和 Join 缓存
3对于标准缓存:解析 CoCacheMetadata,注册元数据 Bean + CacheProxyFactoryBean(标记为主要)
4对于 Join 缓存:解析 JoinCacheMetadata,注册 JoinCacheProxyFactoryBean(标记为主要)

CoCacheAutoConfiguration ​

Spring Boot 自动配置类,负责组装所有 CoCache 组件。

方面详情源码
条件@ConditionalOnCoCacheEnabled、@AutoConfiguration(after = [DataRedisAutoConfiguration::class])--
源文件--CoCacheAutoConfiguration.kt:66

已注册的 Bean ​

Bean 名称类型条件说明
defaultHostClientIdGeneratorClientIdGenerator不存在 ClientIdGenerator 或 HostAddressSupplier Bean使用主机地址作为客户端 ID
cacheFactoryCacheFactory不存在现有 Bean由 ListableBeanFactory 支持的 SpringCacheFactory
coCacheManagerCoCacheManager始终Spring Cache 桥接
cocacheRedisMessageListenerContainerRedisMessageListenerContainerRedisConnectionFactory 可用Redis pub/sub 驱逐事件监听器
cacheEvictedEventBusCacheEvictedEventBus不存在现有 BeanRedisCacheEvictedEventBus
coherentCacheFactoryCoherentCacheFactory不存在现有 BeanDefaultCoherentCacheFactory
cacheSourceFactoryCacheSourceFactory不存在现有 BeanSpringCacheSourceFactory
clientSideCacheFactoryClientSideCacheFactory不存在现有 BeanSpringClientSideCacheFactory
distributedCacheFactoryDistributedCacheFactory不存在现有 BeanRedisDistributedCacheFactory
keyConverterFactoryKeyConverterFactory不存在现有 BeanSpringKeyConverterFactory
cacheProxyFactoryCacheProxyFactory不存在现有 BeanDefaultCacheProxyFactory
joinKeyExtractorFactoryJoinKeyExtractorFactory不存在现有 BeanSpringJoinKeyExtractorFactory
joinCacheProxyFactoryJoinCacheProxyFactory不存在现有 BeanDefaultJoinCacheProxyFactory

自动配置依赖图 ​

mermaid
graph TB
    subgraph Redis["Redis 自动配置"]
        style Redis fill:#161b22,stroke:#6d5dfc,color:#e6edf3
        DRA["DataRedisAutoConfiguration"]
        RT["StringRedisTemplate"]
        RCF["RedisConnectionFactory"]
    end

    subgraph CoCache["CoCacheAutoConfiguration"]
        style CoCache fill:#161b22,stroke:#6d5dfc,color:#e6edf3
        CCG["ClientIdGenerator"]
        CEV["CacheEvictedEventBus"]
        CCF["CoherentCacheFactory"]
        CPF["CacheProxyFactory"]
        CSrcF["CacheSourceFactory"]
        CSF["ClientSideCacheFactory"]
        DCF["DistributedCacheFactory"]
        KCF["KeyConverterFactory"]
        SCF["CacheFactory"]
        CCM["CoCacheManager"]
        JKEF["JoinKeyExtractorFactory"]
        JCPF["JoinCacheProxyFactory"]
    end

    RCF --> CEV
    RT --> CEV
    DRA --> CoCache
    CCG --> CPF
    CCF --> CPF
    CSrcF --> CPF
    CSF --> CPF
    DCF --> CPF
    KCF --> CPF
    SCF --> CCM

相关页面 ​

基于 Apache License 2.0 发布。