说明:这个模块的功能是缓存调用结果,但是我有一个疑问,比如说开始调用的时候,返回结果列表中只有一条数据,另一个进程插入了一条数据,那么下一次调用缓存的那个方法时,那是返回一条结果,还是两条结果了?
Cache 接口定义了两个方法,put 和 get.
public interface Cache {
/**
* API to store value against a key
* @param key Unique identifier for the object being store.
* @param value Value getting store
*/
void put(Object key, Object value);
/**
* API to return stored value using a key.
* @param key Unique identifier for cache lookup
* @return Return stored object against key
*/
Object get(Object key);
}
CacheFactory 定义了获取 Cache 的方法
@SPI(“lru”)
public interface CacheFactory {
/**
* CacheFactory implementation class needs to implement this return underlying cache instance for method against
* url and invocation.
* @param url
* @param invocation
* @return Instance of Cache containing cached value against method url and invocation.
*/
@Adaptive("cache")
Cache getCache(URL url, Invocation invocation);
}
AbstractCacheFactory 实现了 CacheFactory 的基本骨架.
我们先看下 LruCache 吧,LruCache 是最近最久未使用,它的实现原理是借用了 LinkedHashMap 实现的.
public LruCache(URL url) {
final int max = url.getParameter(“cache.size”, 1000);
this.store = new LRUCache<>(max);
}
public class LruCacheFactory extends AbstractCacheFactory {
/**
* Takes url as an method argument and return new instance of cache store implemented by LruCache.
* @param url url of the method
* @return ThreadLocalCache instance of cache
*/
@Override
protected Cache createCache(URL url) {
return new LruCache(url);
}
}
ThreadLocalCache 是借助于 ThreadLocal 实现的.
JCache 是用于缓存的 Java API. 它提供一组通用的类和接口,可用于将 Java 对象临时存储在内存中. 所以即可以使用 JCache 实现,同样的,我也可以使用 Ecache 实现.
ExpiringMap 采用的 ConcurrentHashMap + Thread 实现可自动移除失效数据的结构,所以此处我认为采用 redis 实现效果会更好.
现在来重点关注下 CacheFilter 这个类. 这里实现了缓存结果的具体逻辑.
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
if (cacheFactory != null && ConfigUtils.isNotEmpty(invoker.getUrl().getMethodParameter(invocation.getMethodName(), CACHE_KEY))) {
Cache cache = cacheFactory.getCache(invoker.getUrl(), invocation);
if (cache != null) {
String key = StringUtils.toArgumentString(invocation.getArguments());
Object value = cache.get(key);
if (value != null) {
if (value instanceof ValueWrapper) {
return AsyncRpcResult.newDefaultAsyncResult(((ValueWrapper) value).get(), invocation);
} else {
return AsyncRpcResult.newDefaultAsyncResult(value, invocation);
}
}
Result result = invoker.invoke(invocation);
if (!result.hasException()) {
cache.put(key, new ValueWrapper(result.getValue()));
}
return result;
}
}
return invoker.invoke(invocation);
}
dubbo-filter-validation 包
Validator 类的实例在实际方法调用前对方法输入参数执行验证的扩展.
public interface Validator {
void validate(String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Exception;
}
Validation 获取 Validator 的工厂接口
@SPI(“jvalidation”)
public interface Validation {
/**
* Return the instance of {@link Validator} for a given url.
* @param url Invocation url
* @return Instance of {@link Validator}
*/
@Adaptive(VALIDATION_KEY)
Validator getValidator(URL url);
}
AbstractValidation 抽象类,实现 Validation 的基本骨架.
ValidationFilter 在实际调用方法前,通过 Validation 校验参数的合法性(这个类似于以前在前端使用的 validateEngine 一样,通用的数据校验API).
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
if (validation != null && !invocation.getMethodName().startsWith("$")
&& ConfigUtils.isNotEmpty(invoker.getUrl().getMethodParameter(invocation.getMethodName(), VALIDATION_KEY))) {
try {
Validator validator = validation.getValidator(invoker.getUrl());
if (validator != null) {
validator.validate(invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
}
} catch (RpcException e) {
throw e;
} catch (Throwable t) {
return AsyncRpcResult.newDefaultAsyncResult(t, invocation);
}
}
return invoker.invoke(invocation);
}