前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从Spring缓存源码看大神编程思想

从Spring缓存源码看大神编程思想

作者头像
我的小熊不见了丶
发布2019-05-23 01:02:36
6840
发布2019-05-23 01:02:36
举报
文章被收录于专栏:晓月寒·

从Spring缓存源码看大神编程思想

随着用户的增长我们,数据库承受的压力越来越大,此时我们就需要使用Spring中的缓存,减少用户的操作直击数据库带来的风险。在使用Spring缓存的时候我们通常会使用org.springframework.cache包下的一些注解,但是这篇文章并不是介绍这几个注解的使用方式,而是通过解读该包下的源代码,透过代码看看Spring作者的编程思想。

AbstractCacheManager

这个类在org.springframework.cache.support包下。

initializeCaches

这是这个类的初始化缓存的方法:

代码语言:javascript
复制
public void initializeCaches() {
    //实际存储缓存的map
    private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>(16);
    //缓存中key的集合
    private volatile Set<String> cacheNames = Collections.emptySet();

        // 加载缓存
        Collection<? extends Cache> caches = loadCaches();
        // 加锁,初始化的时候防止其他线程的干扰
        synchronized (this.cacheMap) {
            // 初始化
            this.cacheNames = Collections.emptySet();
            // 清空
            this.cacheMap.clear();
            Set<String> cacheNames = new LinkedHashSet<>(caches.size());
            // 循环从redis中取出的缓存数据放进内存
            for (Cache cache : caches) {
                String name = cache.getName();
                this.cacheMap.put(name, decorateCache(cache));
                cacheNames.add(name);
            }
            this.cacheNames = Collections.unmodifiableSet(cacheNames);
        }
    }

从上面的方法中可以看到,初始化时先从loadCaches()方法加载以前的缓存,经过处理将缓存的key放进set中,将从redis取出的缓存载入内存中。

来看看初始化方法中调用的方法:

loadCaches

代码语言:javascript
复制
@Override
    protected Collection<RedisCache> loadCaches() {

        List<RedisCache> caches = new LinkedList<>();

        for (Map.Entry<String, RedisCacheConfiguration> entry : initialCacheConfiguration.entrySet()) {
            caches.add(createRedisCache(entry.getKey(), entry.getValue()));
        }

        return caches;
    }

createRedisCache

代码语言:javascript
复制
protected RedisCache createRedisCache(String name, @Nullable RedisCacheConfiguration cacheConfig) {
        return new RedisCache(name, cacheWriter, cacheConfig != null ? cacheConfig : defaultCacheConfig);
    }

loadCaches就是从redis中取出缓存。

decorateCache

修饰缓存:

代码语言:javascript
复制
@Override
    protected Cache decorateCache(Cache cache) {
        return (isTransactionAware() ? new TransactionAwareCacheDecorator(cache) : cache);
    }

源码中该方法和事务有关,如果有事务的话会使用事务相关的类包装一层返回,没有的话直接返回。

Collections.unmodifiableSet

该方法返回指定set的不可修改视图。

getCache

再来看获取缓存的的方法:

代码语言:javascript
复制
@Override
    @Nullable
    public Cache getCache(String name) {
        // 先从map中通过key直接取值
        Cache cache = this.cacheMap.get(name);
        if (cache != null) {
            return cache;
        }
        else {
            // Fully synchronize now for missing cache creation...
            synchronized (this.cacheMap) {
                cache = this.cacheMap.get(name);
                if (cache == null) {
                    cache = getMissingCache(name);
                    if (cache != null) {
                        cache = decorateCache(cache);
                        this.cacheMap.put(name, cache);
                        updateCacheNames(name);
                    }
                }
                return cache;
            }
        }
    }

get方法先直接从map中取缓存,如果没取到的话,锁住map再取一次。以防在这个过程中缓存已经被其他的线程刷到map中了。如果还是没取到,会从getMissingCache()方法取一次,代码如下。

getMissingCache

代码语言:javascript
复制
@Override
    protected RedisCache getMissingCache(String name) {
        return allowInFlightCacheCreation ? createRedisCache(name, defaultCacheConfig) : null;
    }

getMissingCache方法从redis中取缓存,如果取到了的话,将缓存修饰一下,放进map里以便下次直接从map中取并且更新存放缓存key的set,之后直接返回缓存。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.03.02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 从Spring缓存源码看大神编程思想
  • AbstractCacheManager
    • initializeCaches
      • loadCaches
        • createRedisCache
      • decorateCache
        • Collections.unmodifiableSet
          • getCache
            • getMissingCache
        相关产品与服务
        云数据库 Redis
        腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档