dubbo源碼分析(三):dubbo服務(wù)暴露-本地服務(wù)暴露分析

@(dubbo源碼分析)[#rpc]

dubbo源碼分析(三):dubbo服務(wù)暴露-本地服務(wù)暴露分析

暴露過程分為兩步

  1. 將本地接口實(shí)現(xiàn)類轉(zhuǎn)化為invoker
  2. 將invoker轉(zhuǎn)化為ExPorter
image.png
  private void exportLocal(URL url) {
        if (!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
            URL local = URL.valueOf(url.toFullString())
                    .setProtocol(Constants.LOCAL_PROTOCOL)
                    .setHost(NetUtils.LOCALHOST)
                    .setPort(0);
            Exporter<?> exporter = protocol.export(
                    proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
            exporters.add(exporter);
            logger.info("Export dubbo service " + interfaceClass.getName() + " to local registry");
        }
    }

一澄步、本地方法轉(zhuǎn)為invoker

 proxyFactory.getInvoker(ref, (Class) interfaceClass, local)

這部分代碼是如何將本地接口實(shí)現(xiàn)類轉(zhuǎn)化為Invoker的
通過debug的方式,進(jìn)入了JavassistProxyFactory

ProxyFactory$Adpative

public com.alibaba.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, com.alibaba.dubbo.common.URL arg2) throws com.alibaba.dubbo.rpc.RpcException {
        if (arg2 == null) throw new IllegalArgumentException("url == null");
        com.alibaba.dubbo.common.URL url = arg2;
        String extName = url.getParameter("proxy", "javassist");
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
        com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
        return extension.getInvoker(arg0, arg1, arg2);
    }

這段代碼需要先說明下
因?yàn)榻涌赑roxyFactory下

 @Adaptive({Constants.PROXY_KEY})
    <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;

故而該方法是通過動(dòng)態(tài)編譯的方式去實(shí)現(xiàn)的

StubProxyFactoryWrapper.getInvoker

public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException {
        return proxyFactory.getInvoker(proxy, type, url);
    }
JavassistProxyFactory.getInvoker

public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        // TODO Wrapper類不能正確處理帶$的類名
        final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
        return new AbstractProxyInvoker<T>(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName,
                                      Class<?>[] parameterTypes,
                                      Object[] arguments) throws Throwable {
                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };
    }
Wrapper.getWrapper

public static Wrapper getWrapper(Class<?> c) {
        while (ClassGenerator.isDynamicClass(c)) // can not wrapper on dynamic class.
            c = c.getSuperclass();

        if (c == Object.class)
            return OBJECT_WRAPPER;

        Wrapper ret = WRAPPER_MAP.get(c);
        if (ret == null) {
            ret = makeWrapper(c);
            WRAPPER_MAP.put(c, ret);
        }
        return ret;
    }
Wrapper.makeWrapper(Class<?> c)//該方法主要是用來實(shí)現(xiàn)類的包裝對(duì)象Wrapper

其中傳入?yún)?shù) Class<?> c即為接口實(shí)現(xiàn)類的Class對(duì)象 绒疗,例如下面

com.alibaba.dubbo.demo.provider.DemoServiceImpl

二、invoker轉(zhuǎn)為exporter

private void exportLocal(URL url) {
        if (!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
            URL local = URL.valueOf(url.toFullString())
                    .setProtocol(Constants.LOCAL_PROTOCOL)
                    .setHost(NetUtils.LOCALHOST)
                    .setPort(0);
            Exporter<?> exporter = protocol.export(
                    proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
            exporters.add(exporter);
            logger.info("Export dubbo service " + interfaceClass.getName() + " to local registry");
        }
    }

其中

protocol.export(proxyFactory.getInvoker(ref, (Class) interfaceClass, local));

拆成兩個(gè)步驟就是

  1. Invoker invoker=proxyFactory.getInvoker(ref, (Class) interfaceClass, local)
  2. protocol.export(invoker)
    接下來我們來看protocol.export(invoker)是如何將invoker轉(zhuǎn)為exporter

protocol.export(invoker)這一步debug進(jìn)去后為

Protocol$Adpative.export//這也是動(dòng)態(tài)編譯生產(chǎn)的類

 public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {
        if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
        com.alibaba.dubbo.common.URL url = arg0.getUrl();
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
        com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
        return extension.export(arg0);
    }
ProtocolFilterWrapper.export

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));
    }
ProtocolFilterWrapper.buildInvokerChain

 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;
    }

ProtocolListenerWrapper.export


public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
            return protocol.export(invoker);
        }
        return new ListenerExporterWrapper<T>(protocol.export(invoker),
                Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
                        .getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
                        
    }
InjvmProtocol.export

 public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        //目的:exporterMap.put(key, this)//key=com.alibaba.dubbo.demo.DemoService, this=InjvmExporter
        return new InjvmExporter<T>(invoker, invoker.getUrl().getServiceKey(), exporterMap);
        
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末字柠,一起剝皮案震驚了整個(gè)濱河市绑榴,隨后出現(xiàn)的幾起案子孽鸡,更是在濱河造成了極大的恐慌蹂午,老刑警劉巖彬碱,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異巷疼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)嚼沿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門估盘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人骡尽,你說我怎么就攤上這事”祝” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵辨图,是天一觀的道長(zhǎng)班套。 經(jīng)常有香客問我,道長(zhǎng)故河,這世上最難降的妖魔是什么吱韭? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任鱼的,我火速辦了婚禮,結(jié)果婚禮上凑阶,老公的妹妹穿的比我還像新娘。我一直安慰自己宙橱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布环葵。 她就那樣靜靜地躺著,像睡著了一般宝冕。 火紅的嫁衣襯著肌膚如雪张遭。 梳的紋絲不亂的頭發(fā)上地梨,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音湿刽,去河邊找鬼。 笑死诈闺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的雅镊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼耸弄,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼卓缰!你這毒婦竟也來了计呈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤茁彭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后理肺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體善镰,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年炫欺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片竣稽。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖娃弓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情台丛,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布挽霉,位于F島的核電站变汪,受9級(jí)特大地震影響侠坎,放射性物質(zhì)發(fā)生泄漏裙盾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一番官、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧徘熔,春花似錦、人聲如沸酷师。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)慕匠。三九已至域醇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間譬挚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工减宣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留玩荠,地道東北人漆腌。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓阶冈,卻偏偏與公主長(zhǎng)得像闷尿,于是被迫代替她去往敵國(guó)和親女坑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容