001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.cache.interceptor; 018 019import org.springframework.cache.Cache; 020import org.springframework.lang.Nullable; 021import org.springframework.util.function.SingletonSupplier; 022 023/** 024 * A base component for invoking {@link Cache} operations and using a 025 * configurable {@link CacheErrorHandler} when an exception occurs. 026 * 027 * @author Stephane Nicoll 028 * @author Juergen Hoeller 029 * @since 4.1 030 * @see org.springframework.cache.interceptor.CacheErrorHandler 031 */ 032public abstract class AbstractCacheInvoker { 033 034 protected SingletonSupplier<CacheErrorHandler> errorHandler; 035 036 037 protected AbstractCacheInvoker() { 038 this.errorHandler = SingletonSupplier.of(SimpleCacheErrorHandler::new); 039 } 040 041 protected AbstractCacheInvoker(CacheErrorHandler errorHandler) { 042 this.errorHandler = SingletonSupplier.of(errorHandler); 043 } 044 045 046 /** 047 * Set the {@link CacheErrorHandler} instance to use to handle errors 048 * thrown by the cache provider. By default, a {@link SimpleCacheErrorHandler} 049 * is used who throws any exception as is. 050 */ 051 public void setErrorHandler(CacheErrorHandler errorHandler) { 052 this.errorHandler = SingletonSupplier.of(errorHandler); 053 } 054 055 /** 056 * Return the {@link CacheErrorHandler} to use. 057 */ 058 public CacheErrorHandler getErrorHandler() { 059 return this.errorHandler.obtain(); 060 } 061 062 063 /** 064 * Execute {@link Cache#get(Object)} on the specified {@link Cache} and 065 * invoke the error handler if an exception occurs. Return {@code null} 066 * if the handler does not throw any exception, which simulates a cache 067 * miss in case of error. 068 * @see Cache#get(Object) 069 */ 070 @Nullable 071 protected Cache.ValueWrapper doGet(Cache cache, Object key) { 072 try { 073 return cache.get(key); 074 } 075 catch (RuntimeException ex) { 076 getErrorHandler().handleCacheGetError(ex, cache, key); 077 return null; // If the exception is handled, return a cache miss 078 } 079 } 080 081 /** 082 * Execute {@link Cache#put(Object, Object)} on the specified {@link Cache} 083 * and invoke the error handler if an exception occurs. 084 */ 085 protected void doPut(Cache cache, Object key, @Nullable Object result) { 086 try { 087 cache.put(key, result); 088 } 089 catch (RuntimeException ex) { 090 getErrorHandler().handleCachePutError(ex, cache, key, result); 091 } 092 } 093 094 /** 095 * Execute {@link Cache#evict(Object)}/{@link Cache#evictIfPresent(Object)} on the 096 * specified {@link Cache} and invoke the error handler if an exception occurs. 097 */ 098 protected void doEvict(Cache cache, Object key, boolean immediate) { 099 try { 100 if (immediate) { 101 cache.evictIfPresent(key); 102 } 103 else { 104 cache.evict(key); 105 } 106 } 107 catch (RuntimeException ex) { 108 getErrorHandler().handleCacheEvictError(ex, cache, key); 109 } 110 } 111 112 /** 113 * Execute {@link Cache#clear()} on the specified {@link Cache} and 114 * invoke the error handler if an exception occurs. 115 */ 116 protected void doClear(Cache cache, boolean immediate) { 117 try { 118 if (immediate) { 119 cache.invalidate(); 120 } 121 else { 122 cache.clear(); 123 } 124 } 125 catch (RuntimeException ex) { 126 getErrorHandler().handleCacheClearError(ex, cache); 127 } 128 } 129 130}