乐于分享
好东西不私藏

2.4.3 源码级拆解 Spring Boot 缓存:从 @ConditionalOnBean 到 CacheConfigurationImportSelector 的完整链路

2.4.3 源码级拆解 Spring Boot 缓存:从 @ConditionalOnBean 到 CacheConfigurationImportSelector 的完整链路

在 Spring Boot 中,缓存自动配置的核心是 CacheAutoConfiguration 类,它并非独立工作,而是与 @EnableCaching 注解紧密协作,共同构建了 Spring 的缓存抽象

🧩 触发与装配:@EnableCaching 与 CacheAutoConfiguration 的协作

整个自动配置的启动,始于开发者在配置类或启动类上添加的 @EnableCaching 注解

  • @EnableCaching 导入关键配置:该注解通过 @Import(CachingConfigurationSelector.class) 导入 CachingConfigurationSelector。在默认的 PROXY 模式下,它会向容器注册 ProxyCachingConfiguration 等配置类

  • ProxyCachingConfiguration 创建核心 BeanProxyCachingConfiguration 会创建 CacheInterceptor 拦截器。这个 CacheInterceptor 继承自 CacheAspectSupport,是实现 AOP 缓存逻辑的核心。

  • CacheAutoConfiguration 的条件激活CacheAutoConfiguration 自身带有 @ConditionalOnBean(CacheAspectSupport.class) 条件。这个条件检查容器中是否存在 CacheAspectSupport 类型的 Bean。由于 @EnableCaching 已经通过 ProxyCachingConfiguration 创建了它的子类 CacheInterceptor,所以这个条件得以满足,CacheAutoConfiguration 随之被激活

⚙️ 核心:CacheAutoConfiguration 与缓存提供者选择

CacheAutoConfiguration 激活后,其类定义上的注解和内部类开始工作,以选择合适的 CacheManager

@Configuration(proxyBeanMethods = false)@ConditionalOnClass(CacheManager.class)@ConditionalOnBean(CacheAspectSupport.class)@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")@EnableConfigurationProperties(CacheProperties.class)@Import({ CacheConfigurationImportSelector.class          CacheManagerEntityManagerFactoryDependsOnPostProcessor.class })public class CacheAutoConfiguration {    // ...}
  • 前置条件@ConditionalOnClass(CacheManager.class) 确保 classpath 中存在 CacheManager 接口@ConditionalOnMissingBean 则确保在用户没有自定义 CacheManager 或 cacheResolver 时,自动配置才会生效

  • CacheConfigurationImportSelector:这是选择缓存提供者的核心。它通过 selectImports 方法,根据 classpath 中的依赖和配置,按优先级顺序导入唯一的缓存配置类

📋 缓存提供者优先级与默认选择

CacheConfigurationImportSelector 的 selectImports 方法会按顺序检查条件,并导入第一个匹配的配置类。主要顺序如下

  1. Generic: 当存在多个 CacheManager 时。

  2. JCache (JSR-107): classpath 中存在 javax.cache 相关类。

  3. EhCache 2.x: 存在 EhCacheCacheManager 类。

  4. Hazelcast: 存在 HazelcastInstance 类。

  5. Infinispan: 存在 Infinispan 相关类。

  6. Couchbase: 存在 Couchbase 相关类。

  7. Redis: 存在 RedisConnectionFactory 类。

  8. Caffeine: 存在 Caffeine 相关类。

  9. Simple默认配置,当以上条件均不满足时

如果没有任何特定的缓存库,Spring Boot 会采用 SimpleCacheConfiguration。它基于 ConcurrentHashMap 实现内存缓存,其核心 ConcurrentMapCacheManager 负责管理 ConcurrentMap 缓存实例

🚀 版本演进:Spring Boot 2.x 到 3.x

  • 自动配置注册CacheAutoConfiguration 在 Spring Boot 2.x 中通过 META-INF/spring.factories 文件注册,在 3.x 中则通过 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件注册

  • Jakarta EE 迁移:Spring Boot 3.x 将 javax.cache 相关的包迁移到了 jakarta.cache

💎 总结

整个流程可以总结如下:

  1. 启用:开发者添加 @EnableCaching 注解。

  2. 装配核心组件@EnableCaching 导入配置,创建 CacheInterceptor (继承自 CacheAspectSupport)。

  3. 激活自动配置CacheInterceptor 的存在满足了 CacheAutoConfiguration 的激活条件 (@ConditionalOnBean(CacheAspectSupport.class))。

  4. 选择实现CacheAutoConfiguration 通过 CacheConfigurationImportSelector,根据 classpath 依赖按优先级选择并导入一个具体的缓存提供者配置类(如 RedisCacheConfiguration 或 SimpleCacheConfiguration)。

  5. 创建 CacheManager:被选中的配置类负责创建并注册对应的 CacheManager Bean(如 RedisCacheManager 或 ConcurrentMapCacheManager)。

最终,CacheAutoConfiguration 为应用装配好了一个 CacheManagerCacheInterceptor 会利用这个 CacheManager 来执行具体的缓存读写操作。