dubbo源碼解析(二十一)遠程調用——Listener

遠程調用——Listener

目標:介紹dubbo-rpc-api中的各類listener監聽器的實現邏輯,內容略少,隨便撇兩眼,不是重點。

前言

本文介紹監聽器的相關邏輯。在服務引用和服務發現中監聽器處於的位置請看下面的圖:java

  1. 服務暴露:

dubbo-export

  1. 服務引用:

dubbo-refer

這兩個監聽器所作的工做不是不少,來看看源碼理解一下。git

源碼分析

(一)ListenerInvokerWrapper

該類實現了Invoker,是服務引用監聽器的包裝類。github

1.屬性

/**
 * invoker對象
 */
private final Invoker<T> invoker;

/**
 * 監聽器集合
 */
private final List<InvokerListener> listeners;

用到了裝飾模式,其中不少實現方法直接調用了invoker的方法。api

2.構造方法

public ListenerInvokerWrapper(Invoker<T> invoker, List<InvokerListener> listeners) {
    // 若是invoker爲空則拋出異常
    if (invoker == null) {
        throw new IllegalArgumentException("invoker == null");
    }
    this.invoker = invoker;
    this.listeners = listeners;
    if (listeners != null && !listeners.isEmpty()) {
        // 遍歷監聽器
        for (InvokerListener listener : listeners) {
            if (listener != null) {
                try {
                    // 調用在服務引用的時候進行監聽
                    listener.referred(invoker);
                } catch (Throwable t) {
                    logger.error(t.getMessage(), t);
                }
            }
        }
    }
}

構造方法中直接調用了監聽器的服務引用。app

3.destroy

@Override
public void destroy() {
    try {
        // 銷燬invoker
        invoker.destroy();
    } finally {
        // 銷燬全部監聽的實體域
        if (listeners != null && !listeners.isEmpty()) {
            for (InvokerListener listener : listeners) {
                if (listener != null) {
                    try {
                        listener.destroyed(invoker);
                    } catch (Throwable t) {
                        logger.error(t.getMessage(), t);
                    }
                }
            }
        }
    }
}

該方法是把服務引用的監聽器銷燬。ide

(二)InvokerListenerAdapter

public abstract class InvokerListenerAdapter implements InvokerListener {

    /**
     * 引用服務
     * @param invoker
     * @throws RpcException
     */
    @Override
    public void referred(Invoker<?> invoker) throws RpcException {
    }

    /**
     * 銷燬
     * @param invoker
     */
    @Override
    public void destroyed(Invoker<?> invoker) {
    }

}

該類是服務引用監聽器的適配類,沒有作實際的操做。源碼分析

(三)DeprecatedInvokerListener

@Activate(Constants.DEPRECATED_KEY)
public class DeprecatedInvokerListener extends InvokerListenerAdapter {

    private static final Logger LOGGER = LoggerFactory.getLogger(DeprecatedInvokerListener.class);

    @Override
    public void referred(Invoker<?> invoker) throws RpcException {
        // 當該引用的服務被廢棄時,打印錯誤日誌
        if (invoker.getUrl().getParameter(Constants.DEPRECATED_KEY, false)) {
            LOGGER.error("The service " + invoker.getInterface().getName() + " is DEPRECATED! Declare from " + invoker.getUrl());
        }
    }

}

該類是當調用廢棄的服務時候打印錯誤日誌。this

(四)ListenerExporterWrapper

該類是服務暴露監聽器包裝類。spa

1.屬性

/**
 * 服務暴露者
 */
private final Exporter<T> exporter;

/**
 * 服務暴露監聽者集合
 */
private final List<ExporterListener> listeners;

用到了裝飾模式,其中不少實現方法直接調用了exporter的方法。日誌

2.構造方法

public ListenerExporterWrapper(Exporter<T> exporter, List<ExporterListener> listeners) {
    if (exporter == null) {
        throw new IllegalArgumentException("exporter == null");
    }
    this.exporter = exporter;
    this.listeners = listeners;
    if (listeners != null && !listeners.isEmpty()) {
        RuntimeException exception = null;
        // 遍歷服務暴露監聽集合
        for (ExporterListener listener : listeners) {
            if (listener != null) {
                try {
                    // 暴露服務監聽
                    listener.exported(this);
                } catch (RuntimeException t) {
                    logger.error(t.getMessage(), t);
                    exception = t;
                }
            }
        }
        if (exception != null) {
            throw exception;
        }
    }
}

該方法中對於每一個服務暴露進行監聽。

3.unexport

@Override
public void unexport() {
    try {
        // 取消暴露
        exporter.unexport();
    } finally {
        if (listeners != null && !listeners.isEmpty()) {
            RuntimeException exception = null;
            // 遍歷監聽集合
            for (ExporterListener listener : listeners) {
                if (listener != null) {
                    try {
                        // 監聽取消暴露
                        listener.unexported(this);
                    } catch (RuntimeException t) {
                        logger.error(t.getMessage(), t);
                        exception = t;
                    }
                }
            }
            if (exception != null) {
                throw exception;
            }
        }
    }
}

該方法是對每一個取消服務暴露的監聽。

(五)ExporterListenerAdapter

public abstract class ExporterListenerAdapter implements ExporterListener {

    /**
     * 暴露服務
     * @param exporter
     * @throws RpcException
     */
    @Override
    public void exported(Exporter<?> exporter) throws RpcException {
    }

    /**
     * 取消暴露服務
     * @param exporter
     * @throws RpcException
     */
    @Override
    public void unexported(Exporter<?> exporter) throws RpcException {
    }

}

該類是服務暴露監聽器的適配類,沒有作實際的操做。

後記

該部分相關的源碼解析地址: https://github.com/CrazyHZM/i...

該文章講解了在服務引用和服務暴露中的各類listener監聽器,其中內容不多。接下來我將開始對rpc模塊的協議protocol進行講解。

相關文章
相關標籤/搜索