spring缓存源码解析


大家都知道spring的缓存机制,可能都会用缓存标签@Cacheable等标签,可是大家有没有想过,为什么在方法上加了标签以后,这个方法就能用缓存呢,作为一名咸鱼coding,当然要知其然也要知其所以然啦,废话不多说,开始吧!

首先我们应该意识到,@Cache运用的是java的动态代理技术,java会给运用了缓存的标签生成一个动态的代理类,如果实现了接口,运用的就是jdk的动态代理,类的动态代理用的是cglib的动态代理技术,那么动态代理类是什么时候生成的呢,首先是spring默认的配置一个advisor(要理解advisor大家首先要知道springAOP的知识):

@Configuration
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {

   @Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor() {
      BeanFactoryCacheOperationSourceAdvisor advisor =
            new BeanFactoryCacheOperationSourceAdvisor();
      advisor.setCacheOperationSource(cacheOperationSource());
      advisor.setAdvice(cacheInterceptor());
      if (this.enableCaching != null) {
         advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));
      }
      return advisor;
   }
 //这是为了后面的切点执行时候需要的,为什么这么说后面我会说明;
   @Bean
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public CacheOperationSource cacheOperationSource() {
      return new AnnotationCacheOperationSource();
   }

//我的理解这是一个增强
   @Bean
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public CacheInterceptor cacheInterceptor() {
      CacheInterceptor interceptor = new CacheInterceptor();
      interceptor.setCacheOperationSources(cacheOperationSource());
      if (this.cacheResolver != null) {
         interceptor.setCacheResolver(this.cacheResolver);
      }
      else if (this.cacheManager != null) {
         interceptor.setCacheManager(this.cacheManager);
      }
      if (this.keyGenerator != null) {
         interceptor.setKeyGenerator(this.keyGenerator);
      }
      if (this.errorHandler != null) {
         interceptor.setErrorHandler(this.errorHandler);
      }
      return interceptor;
   }

}

我们再来看看BeanFactoryCacheOperationSourceAdvisor,
public class BeanFactoryCacheOperationSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

   @Nullable
   private CacheOperationSource cacheOperationSource;

 //CacheOperationSourcePointcut相当于一个切点,运用了CacheOperationSource的判断逻辑

 private final CacheOperationSourcePointcut pointcut = new CacheOperationSourcePointcut() {
      @Override
      @Nullable
      protected CacheOperationSource getCacheOperationSource() {
         return cacheOperationSource;
      }
   };


   /**
    * Set the cache operation attribute source which is used to find cache
    * attributes. This should usually be identical to the source reference
    * set on the cache interceptor itself.
    */
   public void setCacheOperationSource(CacheOperationSource cacheOperationSource) {
      this.cacheOperationSource = cacheOperationSource;
   }

   /**
    * Set the {@link ClassFilter} to use for this pointcut.
    * Default is {@link ClassFilter#TRUE}.
    */
   public void setClassFilter(ClassFilter classFilter) {
      this.pointcut.setClassFilter(classFilter);
   }

   @Override
   public Pointcut getPointcut() {
      return this.pointcut;
   }

}

切面生成了,什么时候执行呢,spring默认的生成代理类的时候规则是这样的,先找到所有的class文件,然后去匹配所有的advisor,如果匹配成功,那么就生成代理类,执行的时候就植入通知(有的叫增强),我们不必知道具体的底层开始类(实际我也没有深究),我们只要知道当匹配advisor的时候会调用CacheOperationSourcePointcut的matches方法,matches方法的匹配逻辑是这样的,查找targetClass类上面是否有四个注解,分别是CacheableCacheEvictCachePut、Caching,如果有这四个注解,则生成TargetClass代理对象,并将注解信息缓存起来,具体的执行代码如下,大家也可以一直跟下去;

@SuppressWarnings("serial")
public class SpringCacheAnnotationParser implements CacheAnnotationParser, Serializable {

   @Override
   @Nullable
   public Collection<CacheOperation> parseCacheAnnotations(Class<?> type) {
      DefaultCacheConfig defaultConfig = getDefaultCacheConfig(type);
      return parseCacheAnnotations(defaultConfig, type);
   }

   @Override
   @Nullable
   public Collection<CacheOperation> parseCacheAnnotations(Method method) {
      DefaultCacheConfig defaultConfig = getDefaultCacheConfig(method.getDeclaringClass());
      return parseCacheAnnotations(defaultConfig, method);
   }

   @Nullable
   protected Collection<CacheOperation> parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae) {
      Collection<CacheOperation> ops = parseCacheAnnotations(cachingConfig, ae, false);
      if (ops != null && ops.size() > 1 && ae.getAnnotations().length > 0) {
         // More than one operation found -> local declarations override interface-declared ones...
         Collection<CacheOperation> localOps = parseCacheAnnotations(cachingConfig, ae, true);
         if (localOps != null) {
            return localOps;
         }
      }
      return ops;
   }

   @Nullable
   private Collection<CacheOperation> parseCacheAnnotations(
         DefaultCacheConfig cachingConfig, AnnotatedElement ae, boolean localOnly) {

      Collection<CacheOperation> ops = null;

      Collection<Cacheable> cacheables = (localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, Cacheable.class) :
            AnnotatedElementUtils.findAllMergedAnnotations(ae, Cacheable.class));
      if (!cacheables.isEmpty()) {
         ops = lazyInit(null);
         for (Cacheable cacheable : cacheables) {
            ops.add(parseCacheableAnnotation(ae, cachingConfig, cacheable));
         }
      }
      Collection<CacheEvict> evicts = (localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, CacheEvict.class) :
            AnnotatedElementUtils.findAllMergedAnnotations(ae, CacheEvict.class));
      if (!evicts.isEmpty()) {
         ops = lazyInit(ops);
         for (CacheEvict evict : evicts) {
            ops.add(parseEvictAnnotation(ae, cachingConfig, evict));
         }
      }
      Collection<CachePut> puts = (localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, CachePut.class) :
            AnnotatedElementUtils.findAllMergedAnnotations(ae, CachePut.class));
      if (!puts.isEmpty()) {
         ops = lazyInit(ops);
         for (CachePut put : puts) {
            ops.add(parsePutAnnotation(ae, cachingConfig, put));
         }
      }
      Collection<Caching> cachings = (localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, Caching.class) :
            AnnotatedElementUtils.findAllMergedAnnotations(ae, Caching.class));
      if (!cachings.isEmpty()) {
         ops = lazyInit(ops);
         for (Caching caching : cachings) {
            Collection<CacheOperation> cachingOps = parseCachingAnnotation(ae, cachingConfig, caching);
            if (cachingOps != null) {
               ops.addAll(cachingOps);
            }
         }
      }

      return ops;
   }

   private <T extends Annotation> Collection<CacheOperation> lazyInit(@Nullable Collection<CacheOperation> ops) {
      return (ops != null ? ops : new ArrayList<>(1));
   }

   CacheableOperation parseCacheableAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, Cacheable cacheable) {
      CacheableOperation.Builder builder = new CacheableOperation.Builder();

      builder.setName(ae.toString());
      builder.setCacheNames(cacheable.cacheNames());
      builder.setCondition(cacheable.condition());
      builder.setUnless(cacheable.unless());
      builder.setKey(cacheable.key());
      builder.setKeyGenerator(cacheable.keyGenerator());
      builder.setCacheManager(cacheable.cacheManager());
      builder.setCacheResolver(cacheable.cacheResolver());
      builder.setSync(cacheable.sync());

      defaultConfig.applyDefault(builder);
      CacheableOperation op = builder.build();
      validateCacheOperation(ae, op);

      return op;
   }

   CacheEvictOperation parseEvictAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, CacheEvict cacheEvict) {
      CacheEvictOperation.Builder builder = new CacheEvictOperation.Builder();

      builder.setName(ae.toString());
      builder.setCacheNames(cacheEvict.cacheNames());
      builder.setCondition(cacheEvict.condition());
      builder.setKey(cacheEvict.key());
      builder.setKeyGenerator(cacheEvict.keyGenerator());
      builder.setCacheManager(cacheEvict.cacheManager());
      builder.setCacheResolver(cacheEvict.cacheResolver());
      builder.setCacheWide(cacheEvict.allEntries());
      builder.setBeforeInvocation(cacheEvict.beforeInvocation());

      defaultConfig.applyDefault(builder);
      CacheEvictOperation op = builder.build();
      validateCacheOperation(ae, op);

      return op;
   }

   CacheOperation parsePutAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, CachePut cachePut) {
      CachePutOperation.Builder builder = new CachePutOperation.Builder();

      builder.setName(ae.toString());
      builder.setCacheNames(cachePut.cacheNames());
      builder.setCondition(cachePut.condition());
      builder.setUnless(cachePut.unless());
      builder.setKey(cachePut.key());
      builder.setKeyGenerator(cachePut.keyGenerator());
      builder.setCacheManager(cachePut.cacheManager());
      builder.setCacheResolver(cachePut.cacheResolver());

      defaultConfig.applyDefault(builder);
      CachePutOperation op = builder.build();
      validateCacheOperation(ae, op);

      return op;
   }

   @Nullable
   Collection<CacheOperation> parseCachingAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, Caching caching) {
      Collection<CacheOperation> ops = null;

      Cacheable[] cacheables = caching.cacheable();
      if (!ObjectUtils.isEmpty(cacheables)) {
         ops = lazyInit(null);
         for (Cacheable cacheable : cacheables) {
            ops.add(parseCacheableAnnotation(ae, defaultConfig, cacheable));
         }
      }
      CacheEvict[] cacheEvicts = caching.evict();
      if (!ObjectUtils.isEmpty(cacheEvicts)) {
         ops = lazyInit(ops);
         for (CacheEvict cacheEvict : cacheEvicts) {
            ops.add(parseEvictAnnotation(ae, defaultConfig, cacheEvict));
         }
      }
      CachePut[] cachePuts = caching.put();
      if (!ObjectUtils.isEmpty(cachePuts)) {
         ops = lazyInit(ops);
         for (CachePut cachePut : cachePuts) {
            ops.add(parsePutAnnotation(ae, defaultConfig, cachePut));
         }
      }

      return ops;
   }

   /**
    * Provides the {@link DefaultCacheConfig} instance for the specified {@link Class}.
    * @param target the class-level to handle
    * @return the default config (never {@code null})
    */
   DefaultCacheConfig getDefaultCacheConfig(Class<?> target) {
      CacheConfig annotation = AnnotatedElementUtils.findMergedAnnotation(target, CacheConfig.class);
      if (annotation != null) {
         return new DefaultCacheConfig(annotation.cacheNames(), annotation.keyGenerator(),
               annotation.cacheManager(), annotation.cacheResolver());
      }
      return new DefaultCacheConfig();
   }

   /**
    * Validates the specified {@link CacheOperation}.
    * <p>Throws an {@link IllegalStateException} if the state of the operation is
    * invalid. As there might be multiple sources for default values, this ensure
    * that the operation is in a proper state before being returned.
    * @param ae the annotated element of the cache operation
    * @param operation the {@link CacheOperation} to validate
    */
   private void validateCacheOperation(AnnotatedElement ae, CacheOperation operation) {
      if (StringUtils.hasText(operation.getKey()) && StringUtils.hasText(operation.getKeyGenerator())) {
         throw new IllegalStateException("Invalid cache annotation configuration on '" +
               ae.toString() + "'. Both 'key' and 'keyGenerator' attributes have been set. " +
               "These attributes are mutually exclusive: either set the SpEL expression used to" +
               "compute the key at runtime or set the name of the KeyGenerator bean to use.");
      }
      if (StringUtils.hasText(operation.getCacheManager()) && StringUtils.hasText(operation.getCacheResolver())) {
         throw new IllegalStateException("Invalid cache annotation configuration on '" +
               ae.toString() + "'. Both 'cacheManager' and 'cacheResolver' attributes have been set. " +
               "These attributes are mutually exclusive: the cache manager is used to configure a" +
               "default cache resolver if none is set. If a cache resolver is set, the cache manager" +
               "won't be used.");
      }
   }

   @Override
   public boolean equals(Object other) {
      return (this == other || other instanceof SpringCacheAnnotationParser);
   }

   @Override
   public int hashCode() {
      return SpringCacheAnnotationParser.class.hashCode();
   }


   /**
    * Provides default settings for a given set of cache operations.
    */
   static class DefaultCacheConfig {

      @Nullable
      private final String[] cacheNames;

      @Nullable
      private final String keyGenerator;

      @Nullable
      private final String cacheManager;

      @Nullable
      private final String cacheResolver;

      public DefaultCacheConfig() {
         this(null, null, null, null);
      }

      private DefaultCacheConfig(@Nullable String[] cacheNames, @Nullable String keyGenerator,
            @Nullable String cacheManager, @Nullable String cacheResolver) {

         this.cacheNames = cacheNames;
         this.keyGenerator = keyGenerator;
         this.cacheManager = cacheManager;
         this.cacheResolver = cacheResolver;
      }

      /**
       * Apply the defaults to the specified {@link CacheOperation.Builder}.
       * @param builder the operation builder to update
       */
      public void applyDefault(CacheOperation.Builder builder) {
         if (builder.getCacheNames().isEmpty() && this.cacheNames != null) {
            builder.setCacheNames(this.cacheNames);
         }
         if (!StringUtils.hasText(builder.getKey()) && !StringUtils.hasText(builder.getKeyGenerator()) &&
               StringUtils.hasText(this.keyGenerator)) {
            builder.setKeyGenerator(this.keyGenerator);
         }

         if (StringUtils.hasText(builder.getCacheManager()) || StringUtils.hasText(builder.getCacheResolver())) {
            // One of these is set so we should not inherit anything
         }
         else if (StringUtils.hasText(this.cacheResolver)) {
            builder.setCacheResolver(this.cacheResolver);
         }
         else if (StringUtils.hasText(this.cacheManager)) {
            builder.setCacheManager(this.cacheManager);
         }
      }

   }

}

至此,启动时扫描生成代理对象的过程就差不多结束了,当代理对象执行时如果匹配成功,则执行CacheInterceptor切面类;

spring缓存的入口类是CacheInterceptor,实现了MethodInterceptor接口,可以看出来这就是一个方法拦截器,拦截所有的执行方法:

public class CacheInterceptor extends CacheAspectSupport implements MethodInterceptor, Serializable {

   @Override
   public Object invoke(final MethodInvocation invocation) throws Throwable {
      Method method = invocation.getMethod();

      CacheOperationInvoker aopAllianceInvoker = new CacheOperationInvoker() {
         @Override
         public Object invoke() {
            try {
               return invocation.proceed();
            }
            catch (Throwable ex) {
               throw new ThrowableWrapper(ex);
            }
         }
      };

      try {
         //execute是父类CacheAspectSupprot的方法,
         return execute(aopAllianceInvoker, invocation.getThis(), method, invocation.getArguments());
      }
      catch (CacheOperationInvoker.ThrowableWrapper th) {
         throw th.getOriginal();
      }
   }

进入execute方法:

protected Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {
   // Check whether aspect is enabled (to cope with cases where the AJ is pulled in automatically)
   //检查是否已经初始化完成 
 if (this.initialized) {
      Class<?> targetClass = getTargetClass(target);
      Collection<CacheOperation> operations = getCacheOperationSource().getCacheOperations(method, targetClass);
      if (!CollectionUtils.isEmpty(operations)) {
         return execute(invoker, method, new CacheOperationContexts(operations, method, args, target, targetClass));
      }
   }

   return invoker.invoke();
}
getCacheOperationSource()方法返回的是一个CacheOperationSource对象,这是一个接口对象,继承关系如下
所示:


进入AbstractFallbackCacheOperationSource的getCacheOperations方法:

@Override
public Collection<CacheOperation> getCacheOperations(Method method, Class<?> targetClass) {
   if (method.getDeclaringClass() == Object.class) {
      return null;
   }
//cacheKey,缓存key,方法+类保证唯一性
   Object cacheKey = getCacheKey(method, targetClass);
//attributeCache是一个Map,这个Map对象里面存的是CacheOperation的集合,CacheOperation是一个抽象类,
//他的继承对象有CacheableOperation、CacheEvictOperation、CachePutOperation,看名字就知道这是对应的
//注解的封装,一般项目启动的时候就会扫描注解,封装注解信息到attributeCache里面(这个可以debug研究一下)
//所以一般运行到这里cached是直接拿就可以了
 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;
   }
}

AbstractFallbackCacheOperationSource

private Collection<CacheOperation> computeCacheOperations(Method method, Class<?> targetClass) {
   // Don't allow no-public methods as required.
   if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
      return null;
   }

   // The method may be on an interface, but we need attributes from the target class.
   // If the target class is null, the method will be unchanged.
   Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
   // If we are dealing with method with generic parameters, find the original method.
   specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);

   // First try is the method in the target class.
   Collection<CacheOperation> opDef = findCacheOperations(specificMethod);
   if (opDef != null) {
      return opDef;
   }

   // Second try is the caching operation on the target class.
   opDef = findCacheOperations(specificMethod.getDeclaringClass());
   if (opDef != null && ClassUtils.isUserLevelMethod(method)) {
      return opDef;
   }

   if (specificMethod != method) {
      // Fallback is to look at the original method.
      opDef = findCacheOperations(method);
      if (opDef != null) {
         return opDef;
      }
      // Last fallback is the class of the original method.
      opDef = findCacheOperations(method.getDeclaringClass());
      if (opDef != null && ClassUtils.isUserLevelMethod(method)) {
         return opDef;
      }
   }

   return null;
}

AbstractFallbackCacheOperationSource的抽象方法,子类实现

protected abstract Collection<CacheOperation> findCacheOperations(Method method);

  子类AnnotationCacheOperationSource实现:

@Override
protected Collection<CacheOperation> findCacheOperations(final Method method) {
   return determineCacheOperations(new CacheOperationProvider() {
      @Override
      public Collection<CacheOperation> getCacheOperations(CacheAnnotationParser parser) {
          //CacheAnnotationParser是一个接口,SpringCacheAnnotationParser是他的实现类
         return parser.parseCacheAnnotations(method);
      }
   });
}


@Override
public Collection<CacheOperation> parseCacheAnnotations(Method method) {
   DefaultCacheConfig defaultConfig = getDefaultCacheConfig(method.getDeclaringClass());
   return parseCacheAnnotations(defaultConfig, method);
}

protected Collection<CacheOperation> parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae) {
   Collection<CacheOperation> ops = null;

   Collection<Cacheable> cacheables = AnnotatedElementUtils.getAllMergedAnnotations(ae, Cacheable.class);
   if (!cacheables.isEmpty()) {
      ops = lazyInit(ops);
      for (Cacheable cacheable : cacheables) {
         ops.add(parseCacheableAnnotation(ae, cachingConfig, cacheable));
      }
   }
   Collection<CacheEvict> evicts = AnnotatedElementUtils.getAllMergedAnnotations(ae, CacheEvict.class);
   if (!evicts.isEmpty()) {
      ops = lazyInit(ops);
      for (CacheEvict evict : evicts) {
         ops.add(parseEvictAnnotation(ae, cachingConfig, evict));
      }
   }
   Collection<CachePut> puts = AnnotatedElementUtils.getAllMergedAnnotations(ae, CachePut.class);
   if (!puts.isEmpty()) {
      ops = lazyInit(ops);
      for (CachePut put : puts) {
         ops.add(parsePutAnnotation(ae, cachingConfig, put));
      }
   }
   Collection<Caching> cachings = AnnotatedElementUtils.getAllMergedAnnotations(ae, Caching.class);
   if (!cachings.isEmpty()) {
      ops = lazyInit(ops);
      for (Caching caching : cachings) {
         Collection<CacheOperation> cachingOps = parseCachingAnnotation(ae, cachingConfig, caching);
         if (cachingOps != null) {
            ops.addAll(cachingOps);
         }
      }
   }

   return ops;
}
看见了吧,这才是解析注解的真正实现,详细的解析自己看下吧,但是一般解析的操作在项目启动的时候就已经
完成了!

好了,我们再回到CacheAspectSupport的execute方法,这时我们已经找到了注解并解析成了CacheOperation集合,
记下来我们介绍下CacheOperationContexts对象,这个对象其实是对CacheOperation的封装:


private final MultiValueMap<Class<? extends CacheOperation>, CacheOperationContext> contexts =
      new LinkedMultiValueMap<Class<? extends CacheOperation>, CacheOperationContext>();

public CacheOperationContexts(Collection<? extends CacheOperation> operations, Method method,
      Object[] args, Object target, Class<?> targetClass) {

   for (CacheOperation operation : operations) {
  //key是class对象,value是CacheOperationContext
     this.contexts.add(operation.getClass(), getOperationContext(operation, method, args, target, targetClass));
   }
   this.sync = determineSyncFlag(method);
}
protected CacheOperationContext getOperationContext(
      CacheOperation operation, Method method, Object[] args, Object target, Class<?> targetClass) {

 //获取注解的元数据信息
   CacheOperationMetadata metadata = getCacheOperationMetadata(operation, method, targetClass);
   return new CacheOperationContext(metadata, args, target);
}
/**
 * Return the {@link CacheOperationMetadata} for the specified operation.
 * <p>Resolve the {@link CacheResolver} and the {@link KeyGenerator} to be
 * used for the operation.
 * @param operation the operation
 * @param method the method on which the operation is invoked
 * @param targetClass the target type
 * @return the resolved metadata for the operation
 */
protected CacheOperationMetadata getCacheOperationMetadata(
      CacheOperation operation, Method method, Class<?> targetClass) {

   CacheOperationCacheKey cacheKey = new CacheOperationCacheKey(operation, method, targetClass);
   CacheOperationMetadata metadata = this.metadataCache.get(cacheKey);
   if (metadata == null) {
      KeyGenerator operationKeyGenerator;
      if (StringUtils.hasText(operation.getKeyGenerator())) {
         operationKeyGenerator = getBean(operation.getKeyGenerator(), KeyGenerator.class);
      }
      else {
         operationKeyGenerator = getKeyGenerator();
      }
      CacheResolver operationCacheResolver;
      if (StringUtils.hasText(operation.getCacheResolver())) {
         operationCacheResolver = getBean(operation.getCacheResolver(), CacheResolver.class);
      }
      else if (StringUtils.hasText(operation.getCacheManager())) {
         CacheManager cacheManager = getBean(operation.getCacheManager(), CacheManager.class);
         operationCacheResolver = new SimpleCacheResolver(cacheManager);
      }
      else {
         operationCacheResolver = getCacheResolver();
         Assert.state(operationCacheResolver != null, "No CacheResolver/CacheManager set");
      }
      metadata = new CacheOperationMetadata(operation, method, targetClass,
            operationKeyGenerator, operationCacheResolver);
      this.metadataCache.put(cacheKey, metadata);
   }
   return metadata;
}

组装CacheOperationContext对象
public CacheOperationContext(CacheOperationMetadata metadata, Object[] args, Object target) {
   this.metadata = metadata;
   //解析参数
  this.args = extractArgs(metadata.method, args);
   this.target = target;
   //注意这个方法,Cache是个接口,这个是获取Cache的实例,用的什么缓存返回的就是什么实例对象,
//我这里返回的是redisCache:
  this.caches = CacheAspectSupport.this.getCaches(this, metadata.cacheResolver);
   this.cacheNames = createCacheNames(this.caches);
   this.methodCacheKey = new AnnotatedElementKey(metadata.method, metadata.targetClass);
}



再返回execute方法:
private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {
   // Special handling of synchronized invocation
   if (contexts.isSynchronized()) {
      CacheOperationContext context = contexts.get(CacheableOperation.class).iterator().next();
      if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) {
         Object key = generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT);
         Cache cache = context.getCaches().iterator().next();
         try {
            return wrapCacheValue(method, cache.get(key, new Callable<Object>() {
               @Override
               public Object call() throws Exception {
                  return unwrapReturnValue(invokeOperation(invoker));
               }
            }));
         }
         catch (Cache.ValueRetrievalException ex) {
            // The invoker wraps any Throwable in a ThrowableWrapper instance so we
            // can just make sure that one bubbles up the stack.
            throw (CacheOperationInvoker.ThrowableWrapper) ex.getCause();
         }
      }
      else {
         // No caching required, only call the underlying method
         return invokeOperation(invoker);
      }
   }


   // Process any early evictions
   processCacheEvicts(contexts.get(CacheEvictOperation.class), true,
         CacheOperationExpressionEvaluator.NO_RESULT);

   // Check if we have a cached item matching the conditions
   //这里就是判断我们有没有命中缓存
  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) {
      collectPutRequests(contexts.get(CacheableOperation.class),
            CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests);
   }

   Object cacheValue;
   Object returnValue;

   if (cacheHit != null && cachePutRequests.isEmpty() && !hasCachePut(contexts)) {
      // If there are no put requests, just use the cache hit
      cacheValue = cacheHit.get();
      returnValue = wrapCacheValue(method, cacheValue);
   }
   else {
      // Invoke the method if we don't have a cache hit
      returnValue = invokeOperation(invoker);
      cacheValue = unwrapReturnValue(returnValue);
   }

   // Collect any explicit @CachePuts
   collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);

   // Process any collected put requests, either from @CachePut or a @Cacheable miss
   for (CachePutRequest cachePutRequest : cachePutRequests) {
      cachePutRequest.apply(cacheValue);
   }

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

   return returnValue;
}

private Cache.ValueWrapper findCachedItem(Collection<CacheOperationContext> contexts) {
   Object result = CacheOperationExpressionEvaluator.NO_RESULT;
   for (CacheOperationContext context : contexts) {
      if (isConditionPassing(context, result)) {
         //这个才是真正的从缓存客户端获取缓存,可以debug跟进去看看
        Object key = generateKey(context, result);
         Cache.ValueWrapper cached = findInCaches(context, key);
         if (cached != null) {
            return cached;
         }
         else {
            if (logger.isTraceEnabled()) {
               logger.trace("No cache entry for key '" + key + "' in cache(s) " + context.getCacheNames());
            }
         }
      }
   }
   return null;
}
执行过程基本上就是这个样子的啦


猜你喜欢

转载自blog.csdn.net/chengkui1990/article/details/80049980