在 Spring 框架中,@Cacheable 与 @CacheEvict 两个注解分别用于实现缓存操作的哪些具体功能?请简述它们的工作原理及典型使用场景。
考察说明
考察对 Spring 缓存抽象中两个核心注解功能与机制的理解。
回答思路
- 【回答框架 1】@Cacheable 注解用于标记一个方法的返回值需要被缓存。当方法被调用时,Spring 的缓存抽象会先根据缓存名和键(默认是方法参数)在缓存中查找,如果命中则直接返回缓存结果而不再执行方法体;如果未命中则执行方法体,将返回值存入缓存。它是基于 AOP 代理实现的,通过拦截器(CacheInterceptor)在方法调用前后进行处理。
- 【回答框架 2】@CacheEvict 注解用于在方法执行后或执行前(默认是执行后)移除缓存中的指定条目或清空整个缓存。常用在数据更新或删除操作上,以保证缓存与数据库的一致性。它同样通过 AOP 实现,可以指定缓存名、键(key)以及是否清除所有条目(allEntries)。
- 【回答框架 3】这两个注解通常配合使用:对于读多写少的场景,使用 @Cacheable 减少方法调用;对于写操作,使用 @CacheEvict 删除相关缓存,避免脏数据。需要注意的是,缓存操作可能带来数据不一致风险,需结合具体业务设计合适的缓存策略。
- 【关键点 1】@Cacheable 是读操作缓存,命中缓存则不执行方法。
- 【关键点 2】@CacheEvict 用于删除缓存,常用于写操作后。
- 【关键点 3】两者都基于 Spring AOP 代理实现。
- 【关键点 4】@CacheEvict 可配置 beforeInvocation 和 allEntries 属性。
- 【关键点 5】默认缓存键由参数生成,可通过 key 属性自定义。
- 【易错点 1】混淆 @CacheEvict 与 @CachePut 的角色,前者删除缓存,后者更新缓存。
- 【易错点 2】忽视缓存一致性问题,单纯依赖注解导致脏数据。
- 【易错点 3】认为 @Cacheable 能自动处理并发问题,实际需考虑缓存穿透、击穿等场景。