/** * 从缓存中删除所有映射。 */ voidclear(); /** * A (wrapper) object representing a cache value. * AbstractValueAdaptingCache中ValueWrapper接口的实现类为SimpleValueWrapper */ interfaceValueWrapper { /** * Return the actual value in the cache. */ Object get(); } /** * Wrapper exception to be thrown from {@link #get(Object, Callable)} * in case of the value loader callback failing with an exception. * @since 4.3 */ @SuppressWarnings("serial") classValueRetrievalExceptionextendsRuntimeException { privatefinal Object key; publicValueRetrievalException(Object key, Callable<?> loader, Throwable ex) { super(String.format("Value for key '%s' could not be loaded using '%s'", key, loader), ex); this.key = key; } public Object getKey() { returnthis.key; } }
/** * The bean name of the custom {@link org.springframework.cache.CacheManager} to use to * create a default {@link org.springframework.cache.interceptor.CacheResolver} if none * is set already. * <p>Mutually exclusive with the {@link #cacheResolver} attribute. * @see org.springframework.cache.interceptor.SimpleCacheResolver * @see CacheConfig#cacheManager */ String cacheManager()default""; }
@Override publicvoidafterSingletonsInstantiated() { if (getCacheResolver() == null) { // Lazily initialize cache resolver via default cache manager... Assert.state(this.beanFactory != null, "CacheResolver or BeanFactory must be set on cache aspect"); try { setCacheManager(this.beanFactory.getBean(CacheManager.class)); } catch (NoUniqueBeanDefinitionException ex) { thrownewIllegalStateException("No CacheResolver specified, and no unique bean of type " + "CacheManager found. Mark one as primary or declare a specific CacheManager to use.", ex); } catch (NoSuchBeanDefinitionException ex) { thrownewIllegalStateException("No CacheResolver specified, and no bean of type CacheManager found. " + "Register a CacheManager bean or remove the @EnableCaching annotation from your configuration.", ex); } } this.initialized = true; }
publicclassCachingConfigurationSelectorextendsAdviceModeImportSelector<EnableCaching> { //... /** * Return the imports to use if the {@link AdviceMode} is set to {@link AdviceMode#PROXY}. * <p>Take care of adding the necessary JSR-107 import if it is available. */ private String[] getProxyImports() { List<String> result = newArrayList<>(3); result.add(AutoProxyRegistrar.class.getName()); result.add(ProxyCachingConfiguration.class.getName()); if (jsr107Present && jcacheImplPresent) { result.add(PROXY_JCACHE_CONFIGURATION_CLASS); } return StringUtils.toStringArray(result); } //... }
publicabstractclassCacheAspectSupportextendsAbstractCacheInvoker implementsBeanFactoryAware, InitializingBean, SmartInitializingSingleton { //略 @Nullable private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) { // Special handling of synchronized invocation if (contexts.isSynchronized()) { CacheOperationContextcontext= contexts.get(CacheableOperation.class).iterator().next(); if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) { Objectkey= generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT); Cachecache= context.getCaches().iterator().next(); try { return wrapCacheValue(method, handleSynchronizedGet(invoker, key, cache)); } catch (Cache.ValueRetrievalException ex) { // Directly propagate ThrowableWrapper from the invoker, // or potentially also an IllegalArgumentException etc. ReflectionUtils.rethrowRuntimeException(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.ValueWrappercacheHit= findCachedItem(contexts.get(CacheableOperation.class));
// Collect puts from any @Cacheable miss, if no cached item is found List < CachePutRequest > cachePutRequests = newArrayList < > (); if (cacheHit == null) { collectPutRequests(contexts.get(CacheableOperation.class), CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests); }
Object cacheValue; Object returnValue;
if (cacheHit != null && !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);