001/* 002 * Copyright 2002-2016 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.support; 018 019import java.util.ArrayList; 020import java.util.Arrays; 021import java.util.Collection; 022import java.util.Collections; 023import java.util.LinkedHashSet; 024import java.util.List; 025import java.util.Set; 026 027import org.springframework.beans.factory.InitializingBean; 028import org.springframework.cache.Cache; 029import org.springframework.cache.CacheManager; 030import org.springframework.lang.Nullable; 031 032/** 033 * Composite {@link CacheManager} implementation that iterates over 034 * a given collection of delegate {@link CacheManager} instances. 035 * 036 * <p>Allows {@link NoOpCacheManager} to be automatically added to the end of 037 * the list for handling cache declarations without a backing store. Otherwise, 038 * any custom {@link CacheManager} may play that role of the last delegate as 039 * well, lazily creating cache regions for any requested name. 040 * 041 * <p>Note: Regular CacheManagers that this composite manager delegates to need 042 * to return {@code null} from {@link #getCache(String)} if they are unaware of 043 * the specified cache name, allowing for iteration to the next delegate in line. 044 * However, most {@link CacheManager} implementations fall back to lazy creation 045 * of named caches once requested; check out the specific configuration details 046 * for a 'static' mode with fixed cache names, if available. 047 * 048 * @author Costin Leau 049 * @author Juergen Hoeller 050 * @since 3.1 051 * @see #setFallbackToNoOpCache 052 * @see org.springframework.cache.concurrent.ConcurrentMapCacheManager#setCacheNames 053 */ 054public class CompositeCacheManager implements CacheManager, InitializingBean { 055 056 private final List<CacheManager> cacheManagers = new ArrayList<>(); 057 058 private boolean fallbackToNoOpCache = false; 059 060 061 /** 062 * Construct an empty CompositeCacheManager, with delegate CacheManagers to 063 * be added via the {@link #setCacheManagers "cacheManagers"} property. 064 */ 065 public CompositeCacheManager() { 066 } 067 068 /** 069 * Construct a CompositeCacheManager from the given delegate CacheManagers. 070 * @param cacheManagers the CacheManagers to delegate to 071 */ 072 public CompositeCacheManager(CacheManager... cacheManagers) { 073 setCacheManagers(Arrays.asList(cacheManagers)); 074 } 075 076 077 /** 078 * Specify the CacheManagers to delegate to. 079 */ 080 public void setCacheManagers(Collection<CacheManager> cacheManagers) { 081 this.cacheManagers.addAll(cacheManagers); 082 } 083 084 /** 085 * Indicate whether a {@link NoOpCacheManager} should be added at the end of the delegate list. 086 * In this case, any {@code getCache} requests not handled by the configured CacheManagers will 087 * be automatically handled by the {@link NoOpCacheManager} (and hence never return {@code null}). 088 */ 089 public void setFallbackToNoOpCache(boolean fallbackToNoOpCache) { 090 this.fallbackToNoOpCache = fallbackToNoOpCache; 091 } 092 093 @Override 094 public void afterPropertiesSet() { 095 if (this.fallbackToNoOpCache) { 096 this.cacheManagers.add(new NoOpCacheManager()); 097 } 098 } 099 100 101 @Override 102 @Nullable 103 public Cache getCache(String name) { 104 for (CacheManager cacheManager : this.cacheManagers) { 105 Cache cache = cacheManager.getCache(name); 106 if (cache != null) { 107 return cache; 108 } 109 } 110 return null; 111 } 112 113 @Override 114 public Collection<String> getCacheNames() { 115 Set<String> names = new LinkedHashSet<>(); 116 for (CacheManager manager : this.cacheManagers) { 117 names.addAll(manager.getCacheNames()); 118 } 119 return Collections.unmodifiableSet(names); 120 } 121 122}