Spring Boot 3.x中@Cacheable作用于非公开方法的原因探究
Spring Boot 3.x中@Cacheable可作用于非公开方法的原因及文档依据
核心变更原因
Spring Boot 3.x基于Spring Framework 6.x构建,后者对CGLIB代理的默认行为做了关键调整:
- 在Spring Framework 5.x及更早版本(对应Spring Boot 2.x),CGLIB代理默认仅拦截公开(public)方法(
setPublicMethodsOnly参数默认值为true),因此非公开方法上的@Cacheable无法被代理拦截,缓存逻辑不生效。 - Spring Framework 6.0起,
setPublicMethodsOnly的默认值改为false,允许CGLIB代理拦截非公开方法(protected、包私有、private),只要这些方法被Spring缓存切面匹配到,@Cacheable的逻辑就会生效。
同时,Spring的缓存切面(CacheInterceptor)在6.0版本也同步调整了匹配逻辑,不再强制要求目标方法必须是公开可见,只要代理能拦截到方法,就会应用缓存注解配置。
官方文档依据
- Spring Framework 6.0迁移指南:明确标注了CGLIB代理的默认行为变更——
org.springframework.cglib.proxy.Enhancer的setPublicMethodsOnly属性默认值从true改为false,允许代理非公开方法。 - Spring Framework缓存官方文档:更新了关于缓存注解方法可见性的描述,补充说明当使用CGLIB代理且开启非公开方法拦截时,
@Cacheable可作用于非公开方法(此前文档仅强调代理模式下优先使用公开方法,现在明确了新默认行为下的支持范围)。
行为差异验证
你的示例代码正好对应了版本差异:
- Spring Boot 2.7(基于Spring Framework 5.3):默认CGLIB代理仅拦截公开方法,非公开方法
foo()每次调用都会执行,输出6次"string"。 - Spring Boot 3.0+(基于Spring Framework 6.0):默认CGLIB代理允许拦截非公开方法,
foo()第一次调用执行并缓存结果,后续调用直接返回缓存值,仅输出1次"string"。
内容的提问来源于stack exchange,提问作者rechandler
相关产品推荐
相关产品推荐

