Java SPI,Dubbo SPI,Spring SPI
Java SPI
The paper
Similar to the policy design pattern, define the interface and write the full path name of the implementation class in a file. callServiceLoader.load
Returns an iterator, which is internally lazy to load when calledhasNext
Read the file according to the full path namenext
Is instantiated. Essentially, you get the full path name of the interface, install the specification to read the file line by line in that path, load the class with the same classloader, and return. (Source code is very simple, not to say more, use the method to see the picture)
advantages
Similar to the template approach, the interface is defined, and the implementation can be written entirely by a third party, as per the specification.
disadvantages
I said it myself. OnesimpleThe service provider’s loading tool. People source developers did not want to write more easy to use, is to write a demo show operation.
Dubbo SPI
Introduction to the
Liverpoolfc.tv: dubbo.apache.org/zh/docs/v2….
advantages
- The JDK’s standard SPI instantiates all implementations of extension points at once, which is time-consuming to initialize if there is an extension implementation, but wasteful of resources to load without it.
- If the extension point fails to load, you will not even get the name of the extension point. Such as: If the RubyScriptEngine class fails to load because the jruby.jar on which RubyScriptEngine depends does not exist, the class fails to load because the jruby.jar on which RubyScriptEngine depends does not exist. This failure cause is eaten up and does not correspond to Ruby. When a user executes a Ruby script, it will report that Ruby is not supported, rather than the actual failure cause.
- Added support for extension points IoC and AOP, where one extension point can directly setter for injection of other extension points.
But I followed the source code, instead of loading all at once, it was created on call (Java version 1.8.0_211).
Analysis of the
- Since it is enhanced, that is essentially the same, is to get the custom implementation class. I first looked at the file in the directory, which is in the form of key and value, so I guess according to the reinforcement point, it should be according to the key to obtain the specified implementation class. Look at the source code, call
com.alibaba.dubbo.common.extension.ExtensionLoader#getAdaptiveExtension
“, the corresponding file will be parsed and the result is as follows
- adaptive
But there’s no adaptive, likeExtensionFactory
When you get, parse toadaptive
Tag, will be cachedcachedAdaptiveClass
If it does not get one, it will concatenate string + compile to generate one. The code is as follows
package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.Invoker {
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(ex tName);return extension.export(arg0);
}
public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws java.lang.Class {
if (arg1 == null) throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg1;
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(ex tName);return extension.refer(arg0, arg1);
}
public void destroy(a) {throw new UnsupportedOperationException("method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
}
public int getDefaultPort(a) {throw new UnsupportedOperationException("method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!"); }}Copy the code
And then we’re going to find the corresponding implementation, the corresponding line, based on the protocol in the URL
(com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(ex tName);
There is nothing to say after that, call the corresponding refer.
Spring SPI
The framework defines the interface, the third-party JAR package custom implementation, according to the specification in the specified location to define the key, value