(八)過濾器-Filter

序前

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:

https://github.com/nytta

可以給個star,^0^.

發佈了184 篇原創文章 · 獲贊 60 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章