Spring集成Spring-data-redis RedisCacheManager缓存源码分析

在项目中,一般我们会把服务层(service)的一些查询结果和一些数据进行缓存。缓存的种类有很多。这里进行redis作为缓存框架,进行一个缓存的配置。配置前需要先了解一些基本的知识

在Spring中缓存主要有一个缓存接口(Cache)与缓存管理接口(CacheManager)。可以通过扩展这两个接口实现对应的缓存管理。redis就是这样。当然还有很多比如Guava等都对其进行了扩展。这里只看redis的缓存基本架构:

这里写图片描述

首先一个抽象的缓存管理类AbstractCacheManager,对CacheManager进行了基本功能的实现,这个类还实现了InitializingBean接口,这个我们知道在spring中实现这个接口就可以在类初始化完成之后,执行接口的afterPropertiesSet方法,AbstractCacheManager在这个方法中执行了initializeCaches方法,也就是初始化缓存。其代码如下:

        //首先加载缓存。loadCaches是一个模板方法,具体怎么加载子类决定。
        Collection<? extends Cache> caches = loadCaches();

        synchronized (this.cacheMap) {
            //每次初始化都创建一个新的缓存名称Set。代码最后一行,把这个set集合变成只读
            this.cacheNames = Collections.emptySet();
            //清空缓存Map  ConcurrentHashMap
            this.cacheMap.clear();
            //初始化 cacheNames
            //1. 循环遍历子类加载的caches
            Set<String> cacheNames = new LinkedHashSet<String>(caches.size());
            for (Cache cache : caches) {
                String name = cache.getName();
                //加入到缓存map集合中,在加入前要进行对缓存进行装配 decorateCache(cache)
                //decorateCache 这个方法本身就是返回cache。但是子类
                //AbstractTransactionSupportingCacheManager 重写它。这个类从名字可以看出
                //是支持事务。它有一个属性transactionAware默认为false. 如果配置了支持事务,
                //就会把当前cache装配成支持事物的cache 所以后面会有支持事务的配置,配置的就是
                //transactionAware 这个属性为true
                //TransactionAwareCacheDecorator
                this.cacheMap.put(name, decorateCache(cache));
                //2. 把cache的name加入到name集合中
                cacheNames.add(name);
            }
            //set变成只读
            this.cacheNames = Collections.unmodifiableSet(cacheNames);
        }
    }

初始化缓存之后,也实现了基本的获取缓存方法:

public Cache getCache(String name) {
        //根据缓存name直接从自己的cache map中获取
        Cache cache = this.cacheMap.get(name);
        if (cache != null) {
            return cache;
        }
        else {
            //如果没有,那么就同步创建
            synchronized (this.cacheMap) {
                //这里再一次获取,避免在同步前,有线程已经添加进去了。
                cache = this.cacheMap.get(name);
                if (cache == null) {
                    //如果还没有,就调用getMissingCache方法获取。
                    //这个方法可以看作一个模板方法,只不过自己实现了返回null
                    //也就是说默认不创建。子类可以通过重写这个方法进行创建。
                    cache = getMissingCache(name);
                    if (cache != null) {
                        //对创建的cache进行装配
                        cache = decorateCache(cache);
                        //放入缓存 map中
                        this.cacheMap.put(name, cache);
                        //更新缓存名称集合。 上面我们知道缓存名称集合被修改成只读,
                        //所以更新方法里面是创建一个新的,然后size进行加1,再把前面的
                        //添加进去,然后加入新建的这个,再修改成只读
                        updateCacheNames(name);
                    }
                }
                return cache;
            }
        }
    }

当然你也可以直接调用lookupCache方法,该方法就是直接获取。没有后续的步骤


                
  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值