• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TAKETODAY / today-infrastructure / 20224960533

15 Dec 2025 08:11AM UTC coverage: 84.388% (-0.02%) from 84.404%
20224960533

push

github

TAKETODAY
:white_check_mark: 在测试中排除 jacoco 初始化方法以避免干扰

61869 of 78367 branches covered (78.95%)

Branch coverage included in aggregate %.

145916 of 167860 relevant lines covered (86.93%)

3.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.64
today-context/src/main/java/infra/cache/support/AbstractCacheManager.java
1
/*
2
 * Copyright 2017 - 2025 the original author or authors.
3
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see [https://www.gnu.org/licenses/]
16
 */
17
package infra.cache.support;
18

19
import org.jspecify.annotations.Nullable;
20

21
import java.util.Collection;
22
import java.util.Collections;
23
import java.util.LinkedHashSet;
24
import java.util.Set;
25
import java.util.concurrent.ConcurrentHashMap;
26
import java.util.concurrent.ConcurrentMap;
27

28
import infra.beans.factory.InitializingBean;
29
import infra.cache.Cache;
30
import infra.cache.CacheManager;
31

32
/**
33
 * Abstract base class implementing the common {@link CacheManager} methods.
34
 * Useful for 'static' environments where the backing caches do not change.
35
 *
36
 * @author Costin Leau
37
 * @author Juergen Hoeller
38
 * @author Stephane Nicoll
39
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
40
 * @since 2020-08-15 19:18
41
 */
42
public abstract class AbstractCacheManager implements CacheManager, InitializingBean {
2✔
43

44
  private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>(16);
6✔
45

46
  private volatile Set<String> cacheNames = Collections.emptySet();
4✔
47

48
  // Early cache initialization on startup
49

50
  @Override
51
  public void afterPropertiesSet() {
52
    initializeCaches();
2✔
53
  }
1✔
54

55
  /**
56
   * Initialize the static configuration of caches.
57
   * <p>Triggered on startup through {@link #afterPropertiesSet()};
58
   * can also be called to re-initialize at runtime.
59
   *
60
   * @see #loadCaches()
61
   * @since 4.0
62
   */
63
  public void initializeCaches() {
64
    Collection<? extends Cache> caches = loadCaches();
3✔
65

66
    synchronized(this.cacheMap) {
5✔
67
      this.cacheNames = Collections.emptySet();
3✔
68
      this.cacheMap.clear();
3✔
69
      Set<String> cacheNames = new LinkedHashSet<>(caches.size());
6✔
70
      for (Cache cache : caches) {
10✔
71
        String name = cache.getName();
3✔
72
        this.cacheMap.put(name, decorateCache(cache));
8✔
73
        cacheNames.add(name);
4✔
74
      }
1✔
75
      this.cacheNames = Collections.unmodifiableSet(cacheNames);
4✔
76
    }
3✔
77
  }
1✔
78

79
  /**
80
   * Load the initial caches for this cache manager.
81
   * <p>Called by {@link #afterPropertiesSet()} on startup.
82
   * The returned collection may be empty but must not be {@code null}.
83
   */
84
  protected abstract Collection<? extends Cache> loadCaches();
85

86
  // Lazy cache initialization on access
87

88
  @Override
89
  @Nullable
90
  public Cache getCache(String name) {
91
    // Quick check for existing cache...
92
    Cache cache = this.cacheMap.get(name);
6✔
93
    if (cache != null) {
2✔
94
      return cache;
2✔
95
    }
96

97
    // The provider may support on-demand cache creation...
98
    Cache missingCache = getMissingCache(name);
4✔
99
    if (missingCache != null) {
2✔
100
      // Fully synchronize now for missing cache registration
101
      synchronized(this.cacheMap) {
5✔
102
        cache = this.cacheMap.get(name);
6✔
103
        if (cache == null) {
2!
104
          cache = decorateCache(missingCache);
4✔
105
          this.cacheMap.put(name, cache);
6✔
106
          updateCacheNames(name);
3✔
107
        }
108
      }
3✔
109
    }
110
    return cache;
2✔
111
  }
112

113
  @Override
114
  public Collection<String> getCacheNames() {
115
    return this.cacheNames;
3✔
116
  }
117

118
  @Override
119
  public void resetCaches() {
120
    synchronized(this.cacheMap) {
×
121
      for (Cache cache : this.cacheMap.values()) {
×
122
        cache.clear();
×
123
      }
×
124
    }
×
125
  }
×
126

127
  // Common cache initialization delegates for subclasses
128

129
  /**
130
   * Check for a registered cache of the given name.
131
   * In contrast to {@link #getCache(String)}, this method does not trigger
132
   * the lazy creation of missing caches via {@link #getMissingCache(String)}.
133
   *
134
   * @param name the cache identifier (must not be {@code null})
135
   * @return the associated Cache instance, or {@code null} if none found
136
   * @see #getCache(String)
137
   * @see #getMissingCache(String)
138
   * @since 4.0
139
   */
140
  @Nullable
141
  protected final Cache lookupCache(String name) {
142
    return this.cacheMap.get(name);
6✔
143
  }
144

145
  /**
146
   * Update the exposed {@link #cacheNames} set with the given name.
147
   * <p>This will always be called within a full {@link #cacheMap} lock
148
   * and effectively behaves like a {@code CopyOnWriteArraySet} with
149
   * preserved order but exposed as an unmodifiable reference.
150
   *
151
   * @param name the name of the cache to be added
152
   */
153
  private void updateCacheNames(String name) {
154
    Set<String> cacheNames = new LinkedHashSet<>(this.cacheNames);
6✔
155
    cacheNames.add(name);
4✔
156
    this.cacheNames = Collections.unmodifiableSet(cacheNames);
4✔
157
  }
1✔
158

159
  // Overridable template methods for cache initialization
160

161
  /**
162
   * Decorate the given Cache object if necessary.
163
   *
164
   * @param cache the Cache object to be added to this CacheManager
165
   * @return the decorated Cache object to be used instead,
166
   * or simply the passed-in Cache object by default
167
   */
168
  protected Cache decorateCache(Cache cache) {
169
    return cache;
2✔
170
  }
171

172
  /**
173
   * Return a missing cache with the specified {@code name}, or {@code null} if
174
   * such a cache does not exist or could not be created on demand.
175
   * <p>Caches may be lazily created at runtime if the native provider supports it.
176
   * If a lookup by name does not yield any result, an {@code AbstractCacheManager}
177
   * subclass gets a chance to register such a cache at runtime. The returned cache
178
   * will be automatically added to this cache manager.
179
   *
180
   * @param name the name of the cache to retrieve
181
   * @return the missing cache, or {@code null} if no such cache exists or could be
182
   * created on demand
183
   * @see #getCache(String)
184
   * @since 4.0
185
   */
186
  @Nullable
187
  protected Cache getMissingCache(String name) {
188
    return null;
2✔
189
  }
190

191
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc