0. "如果内心光明,那society也会是光明的"这话感觉很没有意义
先说回缘起(最近会有意无意的留意话题最初的起因):
- 在使用某框架的级联缓存(jvm缓存+分布式缓存)的时候,猜想是通过spring的应用事件监听机制实现的,感觉复杂度有点高。
- 后面有空的时候,看了下源码,发现其实是维护了多个CacheManager
- 一开始觉得奇怪,会怀疑人生:多个CacheManager有意义嘛?
- 这还没完,一番查找后,发现spring.cache早已提供了
CompositeCacheManager
,很好的通过1个CacheManager解决了问题,并且复杂度很低!(味道很不错,孩子很喜欢)
CompositeManager 可以认为是 代理+迭代器 组合的设计模式的一次很好的实践
1. 先从外观上打摩
@Configuration
@ConditionalOnClass(DemoRedissonConfiguration.class)
@DependsOn(value = "demoRedissonConfiguration")
@EnableCaching
public class DemoCacheConfiguration extends CachingConfigurerSupport {
private RedissonClient redissonClient;
@Autowired(required = false)
public void setRedissonClient(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
// 就是这么容易构造
@Override
public CacheManager cacheManager() {
return new CompositeCacheManager(localCacheManager(), distributedCacheManager());
}
// 分布式缓存
private CacheManager distributedCacheManager() {
Map<String, CacheConfig> config = Maps.newHashMap();
Arrays.stream(CacheEnum.values()).filter(Objects::nonNull).forEach(var -> {
String cacheName = var.getName();
DemoCacheConfig cacheConfig = var.getConfig();
CacheConfig redissonCacheConfig = new CacheConfig(cacheConfig.getExpireInSec(), cacheConfig.getExpireInSec());
config.put(cacheName, redissonCacheConfig);
});
return new RedissonSpringCacheManager(this.redissonClient, config);
}
// JVM缓存
private CacheManager localCacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
List<CaffeineCache> caches = Arrays.stream(CacheEnum.values()).filter(Objects::nonNull).map(var -> {
String cacheName = var.getName();
DemoCacheConfig cacheConfig = var.getConfig();
return new CaffeineCache(cacheName,
Caffeine
.newBuilder()
.initialCapacity(cacheConfig.getInitialCapacity())
.maximumSize(cacheConfig.getMaximumSize())
.expireAfterWrite(cacheConfig.getExpireInSec(), TimeUnit.SECONDS)
.build());
}).collect(Collectors.toList());
cacheManager.setCaches(caches);
return cacheManager;
}
}
2. 再看一下内部结构
简单的简单、扼要
package org.springframework.cache.support;
public class CompositeCacheManager implements CacheManager, InitializingBean {
private final List<CacheManager> cacheManagers = new ArrayList<>();
private boolean fallbackToNoOpCache = false;
/**
* Construct an empty CompositeCacheManager, with delegate CacheManagers to
* be added via the {@link #setCacheManagers "cacheManagers"} property.
*/
public CompositeCacheManager() {
}
/**
* Construct a CompositeCacheManager from the given delegate CacheManagers.
* @param cacheManagers the CacheManagers to delegate to
*/
public CompositeCacheManager(CacheManager... cacheManagers) {
setCacheManagers(Arrays.asList(cacheManagers));
}
/**
* Specify the CacheManagers to delegate to.
*/
public void setCacheManagers(Collection<CacheManager> cacheManagers) {
this.cacheManagers.addAll(cacheManagers);
}
/**
* Indicate whether a {@link NoOpCacheManager} should be added at the end of the delegate list.
* In this case, any {@code getCache} requests not handled by the configured CacheManagers will
* be automatically handled by the {@link NoOpCacheManager} (and hence never return {@code null}).
*/
public void setFallbackToNoOpCache(boolean fallbackToNoOpCache) {
this.fallbackToNoOpCache = fallbackToNoOpCache;
}
@Override
public void afterPropertiesSet() {
if (this.fallbackToNoOpCache) {
this.cacheManagers.add(new NoOpCacheManager());
}
}
@Override
@Nullable
public Cache getCache(String name) {
for (CacheManager cacheManager : this.cacheManagers) {
Cache cache = cacheManager.getCache(name);
if (cache != null) {
return cache;
}
}
return null;
}
@Override
public Collection<String> getCacheNames() {
Set<String> names = new LinkedHashSet<>();
for (CacheManager manager : this.cacheManagers) {
names.addAll(manager.getCacheNames());
}
return Collections.unmodifiableSet(names);
}
}