序
本文主要研究一下JetCache的缓存构建
invokeWithCached
com/alicp/jetcache/anno/method/CacheHandler.java
private static Object invokeWithCached(CacheInvokeContext context)
throws Throwable {
CacheInvokeConfig cic = context.getCacheInvokeConfig();
CachedAnnoConfig cac = cic.getCachedAnnoConfig();
Cache cache = context.getCacheFunction().apply(context, cac);
if (cache == null) {
logger.error("no cache with name: " + context.getMethod());
return invokeOrigin(context);
}
Object key = ExpressionUtil.evalKey(context, cic.getCachedAnnoConfig());
if (key == null) {
return loadAndCount(context, cache, key);
}
if (!ExpressionUtil.evalCondition(context, cic.getCachedAnnoConfig())) {
return loadAndCount(context, cache, key);
}
try {
CacheLoader loader = new CacheLoader() {
@Override
public Object load(Object k) throws Throwable {
Object result = invokeOrigin(context);
context.setResult(result);
return result;
}
@Override
public boolean vetoCacheUpdate() {
return !ExpressionUtil.evalPostCondition(context, cic.getCachedAnnoConfig());
}
};
Object result = cache.computeIfAbsent(key, loader);
return result;
} catch (CacheInvokeException e) {
throw e.getCause();
}
}
invokeWithCached先通过context.getCacheFunction().apply(context, cac)去获取缓存
setCacheFunction
com/alicp/jetcache/anno/support/CacheContext.java
public CacheInvokeContext createCacheInvokeContext(ConfigMap configMap) {
CacheInvokeContext c = newCacheInvokeContext();
c.setCacheFunction((invokeContext, cacheAnnoConfig) -> {
Cache cache = cacheAnnoConfig.getCache();
if (cache == null) {
if (cacheAnnoConfig instanceof CachedAnnoConfig) {
cache = createCacheByCachedConfig((CachedAnnoConfig) cacheAnnoConfig, invokeContext);
} else if ((cacheAnnoConfig instanceof CacheInvalidateAnnoConfig) || (cacheAnnoConfig instanceof CacheUpdateAnnoConfig)) {
CacheInvokeConfig cacheDefineConfig = configMap.getByCacheName(cacheAnnoConfig.getArea(), cacheAnnoConfig.getName());
if (cacheDefineConfig == null) {
String message = "can't find @Cached definition with area=" + cacheAnnoConfig.getArea()
+ " name=" + cacheAnnoConfig.getName() +
", specified in " + cacheAnnoConfig.getDefineMethod();
CacheConfigException e = new CacheConfigException(message);
logger.error("Cache operation aborted because can't find @Cached definition", e);
return null;
}
cache = createCacheByCachedConfig(cacheDefineConfig.getCachedAnnoConfig(), invokeContext);
}
cacheAnnoConfig.setCache(cache);
}
return cache;
});
return c;
}
createCacheInvokeContext设置了cacheFunction,使用了双重检锁去构建cache,对于CachedAnnoConfig是走了createCacheByCachedConfig
createCacheByCachedConfig
com/alicp/jetcache/anno/support/CacheContext.java
private Cache createCacheByCachedConfig(CachedAnnoConfig ac, CacheInvokeContext invokeContext) {
String area = ac.getArea();
String cacheName = ac.getName();
if (CacheConsts.isUndefined(cacheName)) {
cacheName = configProvider.createCacheNameGenerator(invokeContext.getHiddenPackages())
.generateCacheName(invokeContext.getMethod(), invokeContext.getTargetObject());
}
Cache cache = __createOrGetCache(ac, area, cacheName);
return cache;
}
public Cache __createOrGetCache(CachedAnnoConfig cachedAnnoConfig, String area, String cacheName) {
String fullCacheName = area + "_" + cacheName;
Cache cache = cacheManager.getCacheWithoutCreate(area, cacheName);
if (cache == null) {
synchronized (this) {
cache = cacheManager.getCacheWithoutCreate(area, cacheName);
if (cache == null) {
if (globalCacheConfig.isAreaInCacheName()) {
// for compatible reason, if we use default configuration, the prefix should same to that version <=2.4.3
cache = buildCache(cachedAnnoConfig, area, fullCacheName);
} else {
cache = buildCache(cachedAnnoConfig, area, cacheName);
}
cacheManager.putCache(area, cacheName, cache);
}
}
}
return cache;
}
__createOrGetCache再次使用双重检锁通过buildCache去构建Cache,默认globalCacheConfig.isAreaInCacheName()为false,构建完放入cacheManager
buildCache
com/alicp/jetcache/anno/support/CacheContext.java
protected Cache buildCache(CachedAnnoConfig cachedAnnoConfig, String area, String cacheName) {
Cache cache;
if (cachedAnnoConfig.getCacheType() == CacheType.LOCAL) {
cache = buildLocal(cachedAnnoConfig, area);
} else if (cachedAnnoConfig.getCacheType() == CacheType.REMOTE) {
cache = buildRemote(cachedAnnoConfig, area, cacheName);
} else {
Cache local = buildLocal(cachedAnnoConfig, area);
Cache remote = buildRemote(cachedAnnoConfig, area, cacheName);
boolean useExpireOfSubCache = cachedAnnoConfig.getLocalExpire() > 0;
cache = MultiLevelCacheBuilder.createMultiLevelCacheBuilder()
.expireAfterWrite(remote.config().getExpireAfterWriteInMillis(), TimeUnit.MILLISECONDS)
.addCache(local, remote)
.useExpireOfSubCache(useExpireOfSubCache)
.cacheNullValue(cachedAnnoConfig.isCacheNullValue())
.buildCache();
}
cache.config().setRefreshPolicy(cachedAnnoConfig.getRefreshPolicy());
cache = new CacheHandler.CacheHandlerRefreshCache(cache);
cache.config().setCachePenetrationProtect(globalCacheConfig.isPenetrationProtect());
PenetrationProtectConfig protectConfig = cachedAnnoConfig.getPenetrationProtectConfig();
if (protectConfig != null) {
cache.config().setCachePenetrationProtect(protectConfig.isPenetrationProtect());
cache.config().setPenetrationProtectTimeout(protectConfig.getPenetrationProtectTimeout());
}
if (configProvider.getCacheMonitorManager() != null) {
configProvider.getCacheMonitorManager().addMonitors(area, cacheName, cache);
}
return cache;
}
buildCache根据CacheType去构建,对于REMOTE是执行buildRemote
buildRemote
protected Cache buildRemote(CachedAnnoConfig cachedAnnoConfig, String area, String cacheName) {
ExternalCacheBuilder cacheBuilder = (ExternalCacheBuilder) globalCacheConfig.getRemoteCacheBuilders().get(area);
if (cacheBuilder == null) {
throw new CacheConfigException("no remote cache builder: " + area);
}
cacheBuilder = (ExternalCacheBuilder) cacheBuilder.clone();
if (cachedAnnoConfig.getExpire() > 0 ) {
cacheBuilder.expireAfterWrite(cachedAnnoConfig.getExpire(), cachedAnnoConfig.getTimeUnit());
}
if (cacheBuilder.getConfig().getKeyPrefix() != null) {
cacheBuilder.setKeyPrefix(cacheBuilder.getConfig().getKeyPrefix() + cacheName);
} else {
cacheBuilder.setKeyPrefix(cacheName);
}
if (!CacheConsts.isUndefined(cachedAnnoConfig.getKeyConvertor())) {
cacheBuilder.setKeyConvertor(configProvider.parseKeyConvertor(cachedAnnoConfig.getKeyConvertor()));
}
if (!CacheConsts.isUndefined(cachedAnnoConfig.getSerialPolicy())) {
cacheBuilder.setValueEncoder(configProvider.parseValueEncoder(cachedAnnoConfig.getSerialPolicy()));
cacheBuilder.setValueDecoder(configProvider.parseValueDecoder(cachedAnnoConfig.getSerialPolicy()));
}
cacheBuilder.setCacheNullValue(cachedAnnoConfig.isCacheNullValue());
return cacheBuilder.buildCache();
}
这里获取remote的cacheBuilder,进行clone,然后根据cachedAnnoConfig进行属性覆盖,然后执行cacheBuilder.buildCache()构建;这里keyPrefix默认为null,所以这里的keyPrefix为不带aera的cacheName;ExternalCacheBuilder有MockRemoteCacheBuilder、RedisLettuceCacheBuilder两个子类。
小结
JetCache延迟构建Cache,通过CacheContext.buildCache根据cacheType进行构建。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。