玩转Spring Cache --- @Cacheable/@CachePut/@CacheEvict注解的原理深度剖析和使用【享学Spring】(中)

简介: 玩转Spring Cache --- @Cacheable/@CachePut/@CacheEvict注解的原理深度剖析和使用【享学Spring】(中)

处理缓存注解的步骤总结


Spring Cache是Spring框架的核心模块之一,不可谓不重要。用了好几篇文章专门来讲解使用、分析原理。下面按照正常的思路,我把Spring处理的步骤总结如下:


  1. CacheOperation封装了@CachePut、@Cacheable、@CacheEvict(下称三大缓存注解)的属性信息,以便于拦截的时候能直接操作此对象来执行逻辑。
  2. 1. 解析三大注解到CacheOperation的过程是由CacheAnnotationParser完成的
  3. CacheAnnotationSource代表缓存属性源,非常非常重要的一个概念。它提供接口方法来获取目标方法的CacheOperation集合。由上可知,这个具体工作是委托给CacheAnnotationParser去完成的
  4. BeanFactoryCacheOperationSourceAdvisor它代表增强器,至于需要增强哪些类呢???就是看有没有存在CacheOperation属性的方法
  5. CacheInterceptor实现了MethodInterceptor接口,在Spring AOP中实现对执行方法的拦截。在调用invoke执行目标方法前后,通过CacheAnnotationSource获取到方法所有的缓存操作属性,从而一个个的执行
  6. 执行的时候,每一个CacheOperation最后被封装成了CacheOperationContext,而CacheOperationContext最终通过CacheResolver解析出缓存对象Cache(可能是多个)
  7. 最后最后最后,CacheInterceptor调用其父类AbstractCacheInvoker执行对应的doPut / doGet / doEvict / doClear 等等。(可以处理执行异常)


CacheProxyFactoryBean:手动实现Cache功能


其实ProxyFactoryBean的设计模式在Spring AOP中已经非常不陌生了:【小家Spring】面向切面编程Spring AOP创建代理的方式:ProxyFactoryBean、ProxyFactory、AspectJProxyFactory(JDK Proxy和CGLIB)


如下截图,Spring内有非常多的xxxProxyFactoryBean的实现:


image.png


如果说把@EnableCaching称为自动模式的话,那使用CacheProxyFactoryBean就完全是手动档。话不多说,此处给个使用Demo就收场了:

@Configuration
public class RootConfig {
    @Bean
    public CacheProxyFactoryBean cacheProxyFactoryBean() {
        CacheProxyFactoryBean proxyFactoryBean = new CacheProxyFactoryBean();
        // 使用AnnotationCacheOperationSource来识别三大注解缓存
        proxyFactoryBean.setCacheOperationSources(new AnnotationCacheOperationSource());
        // 设置需要代理的目标类
        CacheDemoService cacheDemoService = new CacheDemoServiceImpl();
        proxyFactoryBean.setTarget(cacheDemoService);
        //proxyFactoryBean.setProxyInterfaces();
        // 设置个性化的一些东西
        CacheManager cacheManager = new ConcurrentMapCacheManager();
        proxyFactoryBean.setCacheManager(cacheManager);
        //proxyFactoryBean.setKeyGenerator();
        //proxyFactoryBean.setCacheResolver();
        return proxyFactoryBean;
    }
}
//@Service // 因为使用了CacheProxyFactoryBean手动额皮质,此处请不要再被扫描进去,否则容器内就出现两个这样的Bean了
public class CacheDemoServiceImpl implements CacheDemoService {
    @Cacheable(cacheNames = "demoCache", key = "#id")
    @Override
    public Object getFromDB(Integer id) {
        System.out.println("模拟去db查询~~~" + id);
        return "hello cache...";
    }
}


测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RootConfig.class, CacheConfig.class})
public class TestSpringBean {
    @Autowired
    private CacheDemoService cacheDemoService;
    @Test
    public void test1() {
        cacheDemoService.getFromDB(1);
        cacheDemoService.getFromDB(1);
    }
}



打印结果:

模拟去db查询~~~1


只输出一套日志:缓存生效

此示例中@EnableCaching可不是打开状态哦,但我们依然能够使用手动档让缓存生效。

使用手动档,我们可以很方便的使用NameMatchCacheOperationSource来根据方法名匹配~~~




相关文章
|
3天前
|
Java
Springboot 使用自定义注解结合AOP方式校验接口参数
Springboot 使用自定义注解结合AOP方式校验接口参数
Springboot 使用自定义注解结合AOP方式校验接口参数
|
4天前
|
存储 缓存 Java
【JavaEE】Spring中注解的方式去获取Bean对象
【JavaEE】Spring中注解的方式去获取Bean对象
3 0
|
4天前
|
存储 Java 对象存储
【JavaEE】Spring中注解的方式去存储Bean对象
【JavaEE】Spring中注解的方式去存储Bean对象
7 0
|
4天前
|
JSON 前端开发 Java
【JAVA进阶篇教学】第七篇:Spring中常用注解
【JAVA进阶篇教学】第七篇:Spring中常用注解
|
4天前
|
缓存 NoSQL Java
Spring Cache 缓存原理与 Redis 实践
Spring Cache 缓存原理与 Redis 实践
215 0
|
4天前
|
缓存 NoSQL Java
spring cache整合redis实现springboot项目中的缓存功能
spring cache整合redis实现springboot项目中的缓存功能
51 1
|
4天前
|
缓存 NoSQL Java
Spring Cache 整合 Redis 做缓存使用~ 快速上手~
Spring Cache 整合 Redis 做缓存使用~ 快速上手~
73 1
|
5月前
|
缓存 NoSQL Java
spring cache使用redis
spring cache使用redis
50 1
|
存储 缓存 NoSQL
玩转Spring Cache --- 整合分布式缓存Redis Cache(使用Lettuce、使用Spring Data Redis)【享学Spring】(上)
玩转Spring Cache --- 整合分布式缓存Redis Cache(使用Lettuce、使用Spring Data Redis)【享学Spring】(上)
玩转Spring Cache --- 整合分布式缓存Redis Cache(使用Lettuce、使用Spring Data Redis)【享学Spring】(上)
|
存储 JSON 移动开发
Spring boot 整合 cache,session,redis
Spring boot 整合 cache,session,redis
578 0