[004][缓存模块]Caffeine缓存自定义构建灵活的Spring Boot缓存管理器本项目代码:https://gitee.com/yunjiao-source/tutorials4j/tree/master/framework在Spring Boot应用中缓存是提升系统性能的重要手段。Caffeine作为高性能的本地缓存库常与Spring的CacheManager抽象整合使用。然而默认的CaffeineCacheManager仅支持全局统一的缓存配置如过期时间、最大容量等无法针对不同业务缓存进行差异化定制。本文将通过分析一个自定义的Caffeine缓存模块展示如何实现支持“每个缓存独立配置”的灵活缓存管理器。一、背景与目标1.1 痛点业务缓存需求各异用户会话缓存需要较短过期时间商品目录缓存可设置较长过期时间且需要自动刷新。默认CaffeineCacheManager的配置是全局的若想差异化只能创建多个CacheManager实例管理复杂。1.2 设计目标支持全局默认配置 每个缓存名称可覆盖配置。复用Spring的CaffeineCacheManager尽量减少侵入。提供线程安全的缓存管理器创建器支持延迟初始化。保持与Spring Boot自动配置的无缝集成。二、模块功能解析项目提供了四个核心类分别负责配置加载、工具方法、缓存管理器创建和个性化缓存生成。2.1CacheCaffeineConfiguration– Spring配置装配Configuration(proxyBeanMethodsfalse)publicclassCacheCaffeineConfiguration{BeanCaffeineObject,Objectcaffeine(CacheCaffeinePropertiesproperties){CaffeineObject,ObjectcaffeineCaffeine.newBuilder();CaffeineUtils.copyOption(caffeine,properties);returncaffeine;}BeanConditionalOnMissingBean(CaffeineCacheManagerCreator.class)CaffeineCacheManagerCreatorcaffeineCacheManagerCreator(CaffeineObject,Objectcaffeine,CacheCaffeinePropertiesproperties){returnnewCaffeineCacheManagerCreator(properties,caffeine);}}作用声明创建Caffeine实例的Bean并通过CaffeineUtils将全局属性如initialCapacity、maximumSize等复制到构建器中。然后创建CaffeineCacheManagerCreator它作为工厂负责生成最终的CacheManager。亮点使用ConditionalOnMissingBean允许用户覆盖默认的创建器实现提供扩展点。2.2CaffeineUtils– 配置复制工具publicinterfaceCaffeineUtils{staticvoidcopyOption(CaffeineObject,Objectcaffeine,CaffeineOptionsoptions){caffeine.initialCapacity(options.getInitialCapacity()).maximumSize(options.getMaximumSize());if(options.getExpireAfterAccess()!null){caffeine.expireAfterAccess(options.getExpireAfterAccess());}// ... 其他可选配置if(Objects.equals(Boolean.TRUE,options.getRecordStats())){caffeine.recordStats();}}}作用将CaffeineOptions包含过期策略、刷新间隔、统计开关等批量设置到Caffeine构建器中。设计声明为接口静态方法便于复用判空处理支持可选配置。2.3CaffeineCacheManagerCreator– 线程安全的单例创建器publicclassCaffeineCacheManagerCreatorimplementsSupplierCaffeineCacheManager{privatefinalCacheCaffeinePropertiesproperties;privatefinalCaffeineObject,Objectcaffeine;privatevolatileCaffeineCacheManagerinstance;OverridepublicCaffeineCacheManagerget(){if(instance!null)returninstance;synchronized(this){if(instance!null)returninstance;instancenewInstance();}returninstance;}publicCaffeineCacheManagernewInstance(){FlexibleCaffeineCacheManagermanagernewFlexibleCaffeineCacheManager(properties);manager.setCaffeine(caffeine);returnmanager;}}作用实现Supplier接口提供单例的CaffeineCacheManager。使用DCL双重检查锁保证线程安全同时避免每次获取都创建新实例。优势延迟加载仅在首次调用get()时才真正构建缓存管理器可作为Spring Bean直接注入也可在需要时手动获取。2.4FlexibleCaffeineCacheManager– 核心个性化逻辑publicclassFlexibleCaffeineCacheManagerextendsCaffeineCacheManager{privatefinalCacheCaffeinePropertiesproperties;OverrideprotectedCacheObject,ObjectcreateNativeCaffeineCache(Stringname){MapString,CaffeineOptionsoptionsMapproperties.getNamedCaches();if(MapUtils.isNotEmpty(optionsMap)optionsMap.containsKey(name)){CaffeineOptionscaffeineOptionsoptionsMap.get(name);caffeineOptions.mergeNullValue(properties);// 未设置的项回填全局值CaffeineObject,ObjectcaffeineCaffeine.newBuilder();CaffeineUtils.copyOption(caffeine,caffeineOptions);log.debug(初始化缓存: {},name);returncaffeine.build();}returnsuper.createNativeCaffeineCache(name);}}关键重写createNativeCaffeineCache(String name)是CaffeineCacheManager中每个缓存创建时调用的方法。我们覆盖它根据缓存名称从properties.getNamedCaches()中查找专属配置。配置合并caffeineOptions.mergeNullValue(properties)将未显式设置的属性如expireAfterWrite为null继承自全局配置避免遗漏。降级处理若没有专属配置则调用父类方法父类会使用默认的Caffeine实例即全局配置来构建缓存。三、自定义扩展的设计精髓3.1 属性模型设计假设CacheCaffeineProperties包含全局配置initialCapacity、maximumSize、expireAfterWrite等。MapString, CaffeineOptions namedCacheskey为缓存名称value为该缓存的个性化配置。CaffeineOptions中定义与全局配置相同的字段并提供一个mergeNullValue方法对于自身为null的属性从传入的默认配置中取值。3.2 为什么需要CaffeineCacheManagerCreator直接暴露FlexibleCaffeineCacheManager作为Bean也可以但创建器的好处单例控制确保整个应用只有一个CacheManager实例Spring默认也如此但通过Supplier可更明确控制创建时机。延迟初始化避免在Spring容器启动阶段过早构建缓存尤其是在缓存配置依赖外部动态参数时。测试友好可mock或替换创建逻辑。3.3 线程安全与性能CaffeineCacheManager本身是线程安全的但createNativeCaffeineCache会被多次调用每个缓存名称调用一次。FlexibleCaffeineCacheManager中每次有专属配置时都会新建一个Caffeine实例这符合预期——不同缓存本就应拥有独立的配置和缓存实例。而CaffeineCacheManagerCreator中的DCL确保全局只有一个管理实例避免了重复创建管理器的开销。四、使用示例与配置4.1 配置文件application.ymltutorials4j:cache:caffeine:allow-null-values:falseinitial-capacity:16maximum-size:1000expire-after-write:60srecord-stats:truenamed-caches:users:expire-after-write:30smaximum-size:500products:expire-after-access:10mrefresh-after-write:5m全局默认写入后60秒过期最大1000条。users缓存写入后30秒过期最大500条覆盖全局过期和最大容量。products缓存访问后10分钟过期写入后5分钟刷新注意refreshAfterWrite需要搭配CacheLoader此处仅为示例。4.2 启用缓存ConfigurationEnableCachingpublicclassMyCacheConfig{BeanpublicCacheManagercacheManager(CaffeineCacheManagerCreatorcreator){returncreator.get();// 获取单例缓存管理器}}或者在自动配置中直接使用CacheCaffeineConfiguration它会自动装配创建器并暴露CacheManager。4.3 业务使用ServicepublicclassProductService{Cacheable(products)publicProductgetProduct(Longid){...}CacheEvict(cacheNamesusers,key#userId)publicvoidevictUser(StringuserId){...}}此时products缓存将应用5分钟刷新10分钟访问过期策略而users缓存则使用30秒写入过期。五、总结通过上述设计我们实现了细粒度配置每个缓存名称可定义独立的过期、容量等参数。线程安全且高效单例管理器 DCL避免重复构造。易扩展通过ConditionalOnMissingBean允许用户替换创建器或缓存管理器。兼容Spring标准继承CaffeineCacheManager所有Spring缓存注解Cacheable等无需改动。Caffeine作为“现代Java本地缓存之王”配合灵活的缓存管理器能让你的应用在性能和业务需求之间取得完美平衡。希望本文的自定义实现能为你的项目提供有益的参考。