序前
dubbo会扫描META-INF/dubbo/internal/,META-INF/dubbo/,META-INF/services/目录下的文件,
比如,过滤器的扩展类,则会扫描com.alibaba.dubbo.rpc.Filter文件的扩展类,如该文件的内容:
afterFilter=lam.dubbo.provider.filter.AfterFilter
beforeFilter=lam.dubbo.provider.filter.BeforeFilter
dubbo扫描扩展类,会先扫描本应用的resources下的文件,然后接着会扫描应用依赖的jar包里的文件。
源码
下面看看dubbo是如果实现过滤器的,在com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper源码中,如下。
//暴露服务时,创建过虑器链子
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));
}
//引用服务时,创建过虑器链子
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
return protocol.refer(type, url);
}
return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
}
//这里使用了责任链模式
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);
if (filters.size() > 0) {
for (int i = filters.size() - 1; i >= 0; i --) {
final Filter filter = filters.get(i);
final Invoker<T> next = last;
last = new Invoker<T>() {
public Class<T> getInterface() {
return invoker.getInterface();
}
public URL getUrl() {
return invoker.getUrl();
}
public boolean isAvailable() {
return invoker.isAvailable();
}
public Result invoke(Invocation invocation) throws RpcException {
return filter.invoke(next, invocation);
}
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
};
}
}
return last;
}
实现
下面看看自定义的几个过虑器扩展类
@Activate(group = {Constants.PROVIDER}, value = "beforeFilter")
public class BeforeFilter implements Filter{
public BeforeFilter(){
System.out.println(getClass().getName() + " constructor");
}
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
System.out.println(String.format("%s.%s(%s) before.",
invocation.getClass().getName(), invocation.getMethodName(), invocation.getParameterTypes()));
return invoker.invoke(invocation);
}
}
@Activate(group = {Constants.PROVIDER}, value = "afterFilter")
public class AfterFilter implements Filter{
public AfterFilter(){
System.out.println(getClass().getName() + " constructor");
}
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
Result result = invoker.invoke(invocation);
System.out.println(String.format("%s.%s(%s) after.",
invocation.getClass().getName(), invocation.getMethodName(), invocation.getParameterTypes()));
return result;
}
}
在dubbo的配置文件再配置上过滤器的标签
<dubbo:provider filter="beforeFilter,afterFilter"/>
可以指定到provider,service标签,不过group要匹配提供者,或者无条件。
可以指定到consumer,reference标签,不过group要匹配消费者,或者无条件。
group也可以同时指定provider和consumer
com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.login([Ljava.lang.Class;@3c8d3e36) before.
07-07 11:50:47:INFO(22) lam.dubbo.provider.api.impl.LoginServiceImpl - login - args:user_0
com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.login([Ljava.lang.Class;@3c8d3e36) after.
<dubbo:provider filter="beforeFilter"/>
com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.login([Ljava.lang.Class;@6d95b191) before.
07-07 11:56:59:INFO(22) lam.dubbo.provider.api.impl.LoginServiceImpl - login - args:user_0
自己写了个RPC:
可以给个star,^0^.