1.概述
在 ProtocolFilterWrapper 中,在服務引用和暴露時,#buildInvokerChain(invoker, key, group) 方法中,基於 Dubbo SPI Active 機制,加載匹配對應的過濾器數組,創建帶有過濾器鏈的 Invoker 對象。代碼如下:
/**
* 創建帶 Filter 鏈的 Invoker 對象
*
* @param invoker Invoker 對象
* @param key 獲取 URL 參數名
* @param group 分組
* @param <T> 泛型
* @return Invoker 對象
*/
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
// 獲得過濾器數組
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
// 倒序循環 Filter ,創建帶 Filter 鏈的 Invoker 對象
if (!filters.isEmpty()) {
for (int i = filters.size() - 1; i >= 0; i--) {
final Filter filter = filters.get(i);
final Invoker<T> next = last;
last = new Invoker<T>() {
@Override
public Class<T> getInterface() {
return invoker.getInterface();
}
@Override
public URL getUrl() {
return invoker.getUrl();
}
@Override
public boolean isAvailable() {
return invoker.isAvailable();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
return filter.invoke(next, invocation);
}
@Override
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
};
}
}
return last;
}
2.ClassLoaderFilter
實現 Filter 接口,類加載器切換過濾器實現類。代碼如下:
@Activate(group = Constants.PROVIDER, order = -30000)
public class ClassLoaderFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
// 獲得原來的類加載器
ClassLoader ocl = Thread.currentThread().getContextClassLoader();
// 切換當前線程的類加載器爲服務接口的類加載器
Thread.currentThread().setContextClassLoader(invoker.getInterface().getClassLoader());
// 服務調用
try {
return invoker.invoke(invocation);
} finally {
// 切換當前線程的類加載器爲原來的類加載器
Thread.currentThread().setContextClassLoader(ocl);
}
}
}
作用是在設計目的中,切換到加載了接口定義的類加載器,以便實現與相同的類加載器上下文一起工作。