Dubbo的Filter实现入口是在ProtocolFilterWrapper,由于ProtocolFilterWrapper是Protocol的包装类,因此会在加载的Extension的时候被自动包装进来,实如今ProtocolFilterWrapper.buildInvokerChain方法数组
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
//得到全部符合条件的Filter(已经排好序的)
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
if (!filters.isEmpty()) {
//构建filter调用链
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;
}
复制代码
List
public List<T> getActivateExtension(URL url, String key, String group) {
//key service.filter
//获取该service自定义filter,以逗号隔开
String value = url.getParameter(key);
return getActivateExtension(url, value == null || value.length() == 0 ? null : Constants.COMMA_SPLIT_PATTERN.split(value), group);
}
复制代码
public List<T> getActivateExtension(URL url, String[] values, String group) {
List<T> exts = new ArrayList<T>();
//自定义filter数组
List<String> names = values == null ? new ArrayList<String>(0) : Arrays.asList(values);
//若是自定义filter包含"-default"就不会加载dubbo自带的filter
if (!names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) {
//经过ExtensionLoader获取全部的filter
getExtensionClasses();
//遍历具备Activate注解的,这个cachedActivates是在getExtensionClasses()中放入的
//dubbo自带的filter都是Activate注解的,不须要手动在配置文件中加入这些filter,
//若是本身也想写全局的,也能够加上Activate注解,这样也会出如今cachedActivates中
for (Map.Entry<String, Activate> entry : cachedActivates.entrySet()) {
String name = entry.getKey();
Activate activate = entry.getValue();
//判断是否符合条件 是否在该组中,分为provider和consumer
if (isMatchGroup(group, activate.group())) {
//获得该filter实例
T ext = getExtension(name);
if (!names.contains(name)
&& !names.contains(Constants.REMOVE_VALUE_PREFIX + name)
&& isActive(activate, url)) {
//若是自定义filter不包含该filter,
//而且自定义filter不包含“-”+该filter,而且isActive就放入exts中
//这里若是不想用dubbo自带的某个filter就能够用“-”+filter名称去除掉
exts.add(ext);
}
}
}
//对这些filter进行排序
Collections.sort(exts, ActivateComparator.COMPARATOR);
}
List<T> usrs = new ArrayList<T>();
//遍历自定义filter数组
for (int i = 0; i < names.size(); i++) {
String name = names.get(i);
//若是filter名称不以-开头而且filter数组不包含“-”+该filter名称
if (!name.startsWith(Constants.REMOVE_VALUE_PREFIX)
&& !names.contains(Constants.REMOVE_VALUE_PREFIX + name)) {
//若是该名称为default
if (Constants.DEFAULT_KEY.equals(name)) {
//若是exts不为空
if (!usrs.isEmpty()) {
//把usrs加入到exts中并放到前面,并清空usrs,
//这里和后面实现了自定义filter和dubbo自带的filter排序功能
//由于看后面最终返回的是exts(有序的)
//举例 filter="filter1,filter2,filter3,default,filter4"
//最终exts顺序就为filter1,filter2,filter3,dubbo符合条件的filter,filter4
//若是没有写default,dubbo自带的会在自定义的前面
exts.addAll(0, usrs);
, usrs.clear();
}
} else {
//若是不包含就放入usrs中
T ext = getExtension(name);
usrs.add(ext);
}
}
}
//变量完后,把usrs剩下的都放到exts中
if (!usrs.isEmpty()) {
exts.addAll(usrs);
}
return exts;
}
复制代码
private Map<String, Class<?>> getExtensionClasses() {
//从缓存中获取
Map<String, Class<?>> classes = cachedClasses.get();
if (classes == null) {
synchronized (cachedClasses) {
classes = cachedClasses.get();
if (classes == null) {
//若是没有就从文件中加载
classes = loadExtensionClasses();
//放到缓存中
cachedClasses.set(classes);
}
}
}
return classes;
}
private Map<String, Class<?>> loadExtensionClasses() {
//获取该类型的SPI默认值
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
if (defaultAnnotation != null) {
String value = defaultAnnotation.value();
if ((value = value.trim()).length() > 0) {
String[] names = NAME_SEPARATOR.split(value);
if (names.length > 1) {
throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()
+ ": " + Arrays.toString(names));
}
//设置默认值
if (names.length == 1) cachedDefaultName = names[0];
}
}
Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
//META-INF/dubbo/internal/ 该文件下查找 com.alibaba.dubbo.rpc.Filter并加载
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
//META-INF/dubbo/ 该文件下查找 com.alibaba.dubbo.rpc.Filter
loadDirectory(extensionClasses, DUBBO_DIRECTORY);
//META-INF/services/ 该文件下查找 com.alibaba.dubbo.rpc.Filter
loadDirectory(extensionClasses, SERVICES_DIRECTORY);
//最终Map<String, Class<?>> extensionClasses
return extensionClasses;
}
复制代码
综上源码解析,dubbo是采用本身的SPI机制,一个serviceBean会被不少层东西包装,其中包含ProtocolFilterWrapper
在转换为export的时候,会调用bash
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
}
复制代码
构建filter链
dubbo的filter也是基于SPI机制,看上面代码能够看到他会去 META-INF/dubbo/internal/、META-INF/dubbo/、META-INF/services/ 该文件下查找 com.alibaba.dubbo.rpc.Filter并加载app