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