Spring缓存源码分析

image.png

源码1

1.@EnableCaching注解,Import导入CachingConfigurationSelector,导入的类是AutoProxyRegistrar和ProxyCachingConfiguration

private String[] getProxyImports() {
List<String> result = new ArrayList<String>();
result.add(AutoProxyRegistrar.class.getName());
result.add(ProxyCachingConfiguration.class.getName());
if (jsr107Present && jcacheImplPresent) {
   result.add(PROXY_JCACHE_CONFIGURATION_CLASS);
}
return result.toArray(new String[result.size()]);
}

源码2

AutoProxyRegistrar是ImportBeanDefinitionRegistrar的实现类,关键是注册InfrastructureAdvisorAutoProxyCreator

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
for (String annoType : annoTypes) {
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
      Boolean.class == proxyTargetClass.getClass()) {
   candidateFound = true;
   if (mode == AdviceMode.PROXY) {
     //关键点:注册InfrastructureAdvisorAutoProxyCreator到IOC容器
      AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
      if ((Boolean) proxyTargetClass) {
         AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
         return;
      }
   }
}
}
}

  public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
      return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
  }


  private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
      RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
      beanDefinition.setSource(source);
      beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
      beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
      registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
      return beanDefinition;
  }

源码3

InfrastructureAdvisorAutoProxyCreator是BeanPostProcessor的实现,也就所有的Bean的实例化&初始化生命周期过程中可以进行加上自定义的逻辑,可以从抽象父类AbstractAutoProxyCreator看生命周期的处理过程中postProcessAfterInitialization方法,

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
   return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//找到与bean符合的advisor,看AbstractAdvisorAutoProxyCreator
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//如果找到合适的Advisor会创建相应的代理类
Object proxy = createProxy(
      bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}

this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

  @Override
  protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
      List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
      if (advisors.isEmpty()) {
          return DO_NOT_PROXY;
      }
      return advisors.toArray();
  }

  protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
 //找到IOC所有的Advisor类型的
      List<Advisor> candidateAdvisors = findCandidateAdvisors();
 //遍历Advisor并通过pointCut找出能与bean匹配的Advisor
      List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
      extendAdvisors(eligibleAdvisors);
      if (!eligibleAdvisors.isEmpty()) {
          eligibleAdvisors = sortAdvisors(eligibleAdvisors);
      }
      return eligibleAdvisors;
  }

  public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
      if (candidateAdvisors.isEmpty()) {
          return candidateAdvisors;
      }
      List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
      for (Advisor candidate : candidateAdvisors) {
          if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
              eligibleAdvisors.add(candidate);
          }
      }
      boolean hasIntroductions = !eligibleAdvisors.isEmpty();
      for (Advisor candidate : candidateAdvisors) {
          if (candidate instanceof IntroductionAdvisor) {
              // already processed
              continue;
          }
   //缓存的Advisor是BeanFactoryCacheOperationSourceAdvisor,且是PointCutAdvisor的实现,执行到这里
          if (canApply(candidate, clazz, hasIntroductions)) {
              eligibleAdvisors.add(candidate);
          }
      }
      return eligibleAdvisors;
  }

  public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
      if (advisor instanceof IntroductionAdvisor) {
          return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
      }
      else if (advisor instanceof PointcutAdvisor) {
   //获取BeanFactoryCacheOperationSourceAdviso的CacheOperationSourcePointcut进行拦截
          PointcutAdvisor pca = (PointcutAdvisor) advisor;
          return canApply(pca.getPointcut(), targetClass, hasIntroductions);
      }
      else {
          // It doesn't have a pointcut so we assume it applies.
          return true;
      }
  }

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
      //CacheOperationSourcePointcut是MethodMatcher实现,找到bean所有方法进行匹配拦截
      for (Class<?> clazz : classes) {
          Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
          for (Method method : methods) {
              if ((introductionAwareMethodMatcher != null &&
                      introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
         //直接看CacheOperationSourcePointcut的matches
                      methodMatcher.matches(method, targetClass)) {
                  return true;
              }
          }
      }

      return false;
  }

源码4

ProxyCachingConfiguration配置BeanFactoryCacheOperationSourceAdvisor到IOC容器

@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor() {
//是一个PointcutAdvisor的实现,Pointcut为CacheOperationSourcePointcut和Advice为CacheInterceptor
BeanFactoryCacheOperationSourceAdvisor advisor =
      new BeanFactoryCacheOperationSourceAdvisor();
//用于扫描缓存相关注解
advisor.setCacheOperationSource(cacheOperationSource());
//CacheInterceptor是MethodInterceptor、InitializingBean的实现
advisor.setAdvice(cacheInterceptor());
advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));
return advisor;
}

源码5

CacheOperationSourcePointcut是一个MethodMatcher匹配拦截的Pointcut,注意是查找类的方法是否有缓存相关注解,找到则匹配通过,直接关注matchs方法

@Override
public boolean matches(Method method, Class<?> targetClass) {
//这里CAS是AnnotationCacheOperationSource
CacheOperationSource cas = getCacheOperationSource();
return (cas != null && !CollectionUtils.isEmpty(cas.getCacheOperations(method, targetClass)));
}


@Override
  public Collection<CacheOperation> getCacheOperations(Method method, Class<?> targetClass) {
      if (method.getDeclaringClass() == Object.class) {
          return null;
      }

      Object cacheKey = getCacheKey(method, targetClass);
      Collection<CacheOperation> cached = this.attributeCache.get(cacheKey);

      if (cached != null) {
          return (cached != NULL_CACHING_ATTRIBUTE ? cached : null);
      }
      else {
   //查找缓存注解
          Collection<CacheOperation> cacheOps = computeCacheOperations(method, targetClass);
          if (cacheOps != null) {
              if (logger.isDebugEnabled()) {
                  logger.debug("Adding cacheable method '" + method.getName() + "' with attribute: " + cacheOps);
              }
              this.attributeCache.put(cacheKey, cacheOps);
          }
          else {
              this.attributeCache.put(cacheKey, NULL_CACHING_ATTRIBUTE);
          }
          return cacheOps;
      }
  }

private Collection<CacheOperation> computeCacheOperations(Method method, Class<?> targetClass) {

      specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);

      // 先查找方法上是否有缓存注解
      Collection<CacheOperation> opDef = findCacheOperations(specificMethod);
      if (opDef != null) {
          return opDef;
      }

      // 先查找类上是否有缓存注解
      opDef = findCacheOperations(specificMethod.getDeclaringClass());
      if (opDef != null && ClassUtils.isUserLevelMethod(method)) {
          return opDef;
      }
      return null;
  }

源码6

CacheInterceptor是MethodInterceptor实现,代理类执行的时候会调用(关注AOP的责任链调用),并且是SmartInitializingSingleton实现(关注afterSingletonsInstantiated方法)

@Override
public void afterSingletonsInstantiated() {
if (getCacheResolver() == null) {
   try {
     //从IOC容器获取CacheManager,这个我们一般会自己配置
      setCacheManager(this.beanFactory.getBean(CacheManager.class));
   }
   catch (NoUniqueBeanDefinitionException ex) {
   }
}
this.initialized = true;
}


  @Override
  public Object invoke(final MethodInvocation invocation) throws Throwable {
 //Aop拦截的时候执行到这里
      Method method = invocation.getMethod();

      CacheOperationInvoker aopAllianceInvoker = new CacheOperationInvoker() {
          @Override
          public Object invoke() {
              try {
       //缓存未命中的时候会执行
                  return invocation.proceed();
              }
              catch (Throwable ex) {
                  throw new ThrowableWrapper(ex);
              }
          }
      };

      try {
          return execute(aopAllianceInvoker, invocation.getThis(), method, invocation.getArguments());
      }
      catch (CacheOperationInvoker.ThrowableWrapper th) {
          throw th.getOriginal();
      }
  }

private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {
      // 处理CacheEvict注解
      processCacheEvicts(contexts.get(CacheEvictOperation.class), true,
              CacheOperationExpressionEvaluator.NO_RESULT);

      // 处理Cacheable注解,查找缓存值
      Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class));

      // Collect puts from any @Cacheable miss, if no cached item is found
      List<CachePutRequest> cachePutRequests = new LinkedList<CachePutRequest>();
      if (cacheHit == null) {
   //未命中添加CachePutRequest,用于业务执行后返回值不为空添加到缓存
          collectPutRequests(contexts.get(CacheableOperation.class),
                  CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests);
      }

      Object cacheValue;
      Object returnValue;

      if (cacheHit != null && cachePutRequests.isEmpty() && !hasCachePut(contexts)) {
          // 缓存命中直接返回,不会再进行AOP的责任链进行执行了,也就不会执行到业务逻辑了
          cacheValue = cacheHit.get();
          returnValue = wrapCacheValue(method, cacheValue);
      }
      else {
          // 缓存未命中,并继续按照AOP责任链执行,最后会执行到业务逻辑
          returnValue = invokeOperation(invoker);
          cacheValue = unwrapReturnValue(returnValue);
      }

      //// 处理CachePuts注解,查找缓存值
      collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);

      //执行缓存未命中的时候添加的CachePutRequest
      for (CachePutRequest cachePutRequest : cachePutRequests) {
          cachePutRequest.apply(cacheValue);
      }

      // Process any late evictions
      processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue);

      return returnValue;
  }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 昨天就把作业做完了,留出时间来今天开始复习,找了一些大宝前几天考试做错的类型的题,今天全部都会做了,背诵了四...
    梦_9295阅读 129评论 0 0
  • 十章:特别的存在 上一章 【目录】 来到驻点外,一阵冷风袭来让那简不由打了个哆嗦,也瞬间清醒。打起精神来,那简!那...
    kay布茨酱阅读 316评论 5 8