View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.cache.support;
18  
19  import java.util.Collection;
20  import java.util.Collections;
21  import java.util.LinkedHashSet;
22  import java.util.Set;
23  import java.util.concurrent.ConcurrentHashMap;
24  import java.util.concurrent.ConcurrentMap;
25  
26  import org.springframework.beans.factory.InitializingBean;
27  import org.springframework.cache.Cache;
28  import org.springframework.cache.CacheManager;
29  
30  /**
31   * Abstract base class implementing the common {@link CacheManager} methods.
32   * Useful for 'static' environments where the backing caches do not change.
33   *
34   * @author Costin Leau
35   * @author Juergen Hoeller
36   * @author Stephane Nicoll
37   * @since 3.1
38   */
39  public abstract class AbstractCacheManager implements CacheManager, InitializingBean {
40  
41  	private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<String, Cache>(16);
42  
43  	private Set<String> cacheNames = new LinkedHashSet<String>(16);
44  
45  
46  	// Early cache initialization on startup
47  
48  	@Override
49  	public void afterPropertiesSet() {
50  		Collection<? extends Cache> caches = loadCaches();
51  
52  		// Preserve the initial order of the cache names
53  		this.cacheMap.clear();
54  		this.cacheNames.clear();
55  		for (Cache cache : caches) {
56  			addCache(cache);
57  		}
58  	}
59  
60  	/**
61  	 * Load the initial caches for this cache manager.
62  	 * <p>Called by {@link #afterPropertiesSet()} on startup.
63  	 * The returned collection may be empty but must not be {@code null}.
64  	 */
65  	protected abstract Collection<? extends Cache> loadCaches();
66  
67  
68  	// Lazy cache initialization on access
69  
70  	@Override
71  	public Cache getCache(String name) {
72  		Cache cache = lookupCache(name);
73  		if (cache != null) {
74  			return cache;
75  		}
76  		else {
77  			Cache missingCache = getMissingCache(name);
78  			if (missingCache != null) {
79  				addCache(missingCache);
80  				return lookupCache(name);  // may be decorated
81  			}
82  			return null;
83  		}
84  	}
85  
86  	@Override
87  	public Collection<String> getCacheNames() {
88  		return Collections.unmodifiableSet(this.cacheNames);
89  	}
90  
91  
92  	// Common cache initialization delegates/callbacks
93  
94  	protected final void addCache(Cache cache) {
95  		this.cacheMap.put(cache.getName(), decorateCache(cache));
96  		this.cacheNames.add(cache.getName());
97  	}
98  
99  	protected final Cache lookupCache(String name) {
100 		return this.cacheMap.get(name);
101 	}
102 
103 	/**
104 	 * Decorate the given Cache object if necessary.
105 	 * @param cache the Cache object to be added to this CacheManager
106 	 * @return the decorated Cache object to be used instead,
107 	 * or simply the passed-in Cache object by default
108 	 */
109 	protected Cache decorateCache(Cache cache) {
110 		return cache;
111 	}
112 
113 	/**
114 	 * Return a missing cache with the specified {@code name} or {@code null} if
115 	 * such cache does not exist or could not be created on the fly.
116 	 * <p>Some caches may be created at runtime in the native provided. If a lookup
117 	 * by name does not yield any result, a subclass gets a chance to register
118 	 * such a cache at runtime. The returned cache will be automatically added to
119 	 * this instance.
120 	 * @param name the name of the cache to retrieve
121 	 * @return the missing cache or {@code null} if no such cache exists or could be
122 	 * created
123 	 * @see #getCache(String)
124 	 */
125 	protected Cache getMissingCache(String name) {
126 		return null;
127 	}
128 
129 }