加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

如何进行高效的源码阅读:以Spring Cache扩展为例带你搞清楚

发布时间:2019-07-27 00:45:29 所属栏目:建站 来源:三旬老汉
导读:摘要 日常开发中,需要用到各种各样的框架来实现API、系统的构建。作为程序员,除了会使用框架还必须要了解框架工作的原理。这样可以便于我们排查问题,和自定义的扩展。那么如何去学习框架呢。通常我们通过阅读文档、查看源码,然后又很快忘记。始终不能

知道如何使用Spring Cache后,我们需要进一步思考,就是如何扩展。那么带着问题出发。
比如Spring Cache不支持批量key的缓存,像上文我们举的例子,我们希望缓存的key是userId,而不是Collection userIds。以userId为key,这样的缓存命中率更高,存储的成本更小。

  1. @Cacheable(cacheNames = "users") 
  2.    public Map<Long, User> getUser(final Collection<Long> userIds) {} 

所以我们要实现对Spring Cache进行扩展。step3中我们已经大致了解了Spring Cache的实现。那么实现这个扩展的功能就是拆分Collection userIds,缓存命中的从缓存中获取,没有命中的,调用源方法。

  1. @Aspect 
  2. @Component 
  3. public class CacheExtenionAspect { 
  4.  
  5.     @Autowired 
  6.     private CacheExtensionManage cacheExtensionManage; 
  7.  
  8.     /** 
  9.      * 返回的结果中缓存命中的从缓存中获取,没有命中的调用原来的方法获取 
  10.      * @param joinPoint 
  11.      * @return 
  12.      */ 
  13.     @Around("@annotation(org.springframework.cache.annotation.Cacheable)") 
  14.     @SuppressWarnings("unchecked") 
  15.     public Object aroundCache(final ProceedingJoinPoint joinPoint) { 
  16.      
  17.         // 修改掉Collection值,cacheResult需要重新构造一个 
  18.         args[0] = cacheResult.getMiss(); 
  19.         try { 
  20.             final Map<Object, Object> notHit = CollectionUtils.isEmpty(cacheResult.getMiss()) ? null 
  21.                     : (Map<Object, Object>) (method.invoke(target, args)); 
  22.             final Map<Object, Object> hits = cacheResult.getHit(); 
  23.             if (Objects.isNull(notHit)) { 
  24.                 return hits; 
  25.             } 
  26.             // 设置缓存 
  27.             cacheResult.getCache().putAll(notHit); 
  28.             hits.putAll(notHit); 
  29.             return hits; 
  30.     } 
  31. 然后扩展Cache,CacheManage 
  32. 重写Cache的查找缓存方法,返回新的CacheResult 
  33.  
  34.   public static Object lookup(final CacheExtension cache, final Object key) { 
  35.         if (key instanceof Collection) { 
  36.             final Collection<Object> originalKeys = ((Collection) key); 
  37.             if (originalKeys == null || originalKeys.isEmpty()) { 
  38.                 return CacheResult.builder().cache(cache).miss( 
  39.                         Collections.emptySet()) 
  40.                         .build(); 
  41.             } 
  42.             final List<Object> keys = originalKeys.stream() 
  43.                     .filter(Objects::nonNull).collect(Collectors.toList()); 
  44.             final Map<Object, Object> hits = cache.getAll(keys); 
  45.             final Set<Object> miss = new HashSet(keys); 
  46.             miss.removeAll(hits.keySet()); 
  47.             return CacheResult.builder().cache(cache).hit(hits).miss(miss).build(); 
  48.         } 
  49.         return null; 
  50.     } 
  51. CacheResult就是新的缓存结果格式 
  52.  
  53.  @Builder 
  54.     @Setter 
  55.     @Getter 
  56.     static class CacheResult { 
  57.         final CacheExtension cache; 
  58.         // 命中的缓存结果 
  59.         final Map<Object, Object> hit; 
  60.         // 需要重新调用源方法的keys 
  61.         private Set<Object> miss; 
  62.     } 

然后扩展CacheManager,没什么重写,就是自定义一种manager类型

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读