Implementation of Listener in dubbo

I want to continue dubbo's source code journey here, learn its design and techniques in the process, and look at the excellent code. I think it will certainly be helpful for our schedule coding. And those open source codes are things that have been tried and tested, and I hope to share with you.

Take ProtocolListener Wrapper as an example. When we look at the source code, we find that it is a standard implementation of decorative class. It has its own copy constructor, which copies the wrapped person in, and then combines the operation of decorative part. Look at the ProtocolListenerWrapper class for code like this:

public class ProtocolListenerWrapper implements Protocol {

    private final Protocol protocol;

    public ProtocolListenerWrapper(Protocol protocol){
        if (protocol == null) {
            throw new IllegalArgumentException("protocol == null");
        }
        this.protocol = protocol;
    }

    public int getDefaultPort() {
        return protocol.getDefaultPort();
    }

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

    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 new ListenerInvokerWrapper<T>(protocol.refer(type, url),
                Collections.unmodifiableList(
                        ExtensionLoader.getExtensionLoader(InvokerListener.class)
                        .getActivateExtension(url, Constants.INVOKER_LISTENER_KEY)));
    }

    public void destroy() {
        protocol.destroy();
    }

}
And we found this code snippet clazz.getConstructor() in Extension Loader to match the decoration pattern mentioned earlier.
These classes are cached as plug-ins in cached Wrapper Classes. The use of this cache is to unlock the key to the listener call implementation.
try {
    clazz.getConstructor(type);
    Set<Class<?>> wrappers = cachedWrapperClasses;
    if (wrappers == null) {
        cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
        wrappers = cachedWrapperClasses;
    }
    wrappers.add(clazz);
} catch (NoSuchMethodException e) {

As you can see above, use a field as a logic of judgment.

The getExtension(String name) method in Extension Loader calls createExtension(String name), which uses cachedWrapper Classes as a parameter to call the warpper class's own replication constructor, so that the decorated class can be packaged accurately, so that it can be persistent when the decorated class is called. The logical code in warpper is implemented by calling clazz.getConstructor method. The code snippet:

Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && wrapperClasses.size() > 0) {
    for (Class<?> wrapperClass : wrapperClasses) {
        instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
    }
}
Looking back at ProtocolListener Wrapper, we can see that inheriting export method from Protocols is the entry method of opening service to the outside world. It returns exporter. In code, it actually returns Listener Exporter Wrapper, which is also a decorative class. However, without using the mechanism mentioned above, we just wrap exporter and listener in class and listener in constructor. Implementation. So we finally found the code to execute listener.
In the development of dubbo, listener is an important extension. When serving the outside world, we should do something we want to do, such as inheriting Exporter Listener.
Write a class to inherit InvokerListener if you want to do something of your own when referring to a service.
 
In addition, as an example, ExporterListener finds that there is an ExporterListener Adapter in his subclass, two empty methods, code:
public abstract class ExporterListenerAdapter implements ExporterListener {

    public void exported(Exporter<?> exporter) throws RpcException {
    }

    public void unexported(Exporter<?> exporter) throws RpcException {
    }

}

This is a trick. When I just mentioned that I want to write extension classes, I don't inherit ExporterListener directly, because direct inheritance interface will force the implementation of two methods, and the author of dubbo in actual coding should also find that these two methods are used in totally different business, so we can only inherit ExporterListener Adapter, so our own business generation. There is no need for an empty method in the code.

Keywords: Java Dubbo

Added by Dan400007 on Wed, 05 Jun 2019 21:58:57 +0300