Extensionloader general use mode
#截取 from ServiceConfig code fragment public
class Serviceconfig<t> extends Abstractserviceconfig {
private static Final long serialversionuid = 3033787999037024738L;
private static final Protocol Protocol = Extensionloader.getextensionloader (Protocol.class). Getadaptiveextension ();
From the above code we can find the Extensionloader method, common to get an extension of the usage.
1. The getextensionloader must be an interface.
2. An SPI annotation must be added to the interface to indicate an extension. Analysis of construction methods
Private final extensionfactory objectfactory;
Private Extensionloader (class<?> type) {
this.type = type;
Objectfactory = (Type = = Extensionfactory.class? Null:ExtensionLoader.getExtensionLoader (Extensionfactory.class). Getadaptiveextension ());
}
The code above we found a new class Extensionfactory What's this for? Extensionfactory there is only one way to get a concrete extension instance based on the type and name.
First, if the extension type is extensionfactory objectfactory =null, otherwise = a self applicable extensionfactory.
Let's look specifically at the GetAdaptiveExtension method of Extensionloader.getextensionloader (Extensionfactory.class). Getadaptiveextension ()
This object is used to store instances of the generated self-applicability, such as protocol$adaptive (which is dynamically spliced). Private Final holder<object>
Cachedadaptiveinstance = new holder<object> ();
Public T getadaptiveextension () {Object instance = Cachedadaptiveinstance.get (); if (instance = = null) {if (Createadaptiveinstanceerror = = null) {synchronized (Cachedadaptiveinstanc
E) {instance = Cachedadaptiveinstance.get (); if (instance = = null) {try {//emphasis created here instance =
Createadaptiveextension ();
Cachedadaptiveinstance.set (instance);
catch (Throwable t) {createadaptiveinstanceerror = t;
throw new IllegalStateException ("Fail to create Adaptive instance:" + t.tostring (), t); else {throw new IllegalStateException ("fail to create Ada"}}}}Ptive instance: "+ createadaptiveinstanceerror.tostring (), createadaptiveinstanceerror);"
} return (T) instance;
}
Let's look at Createadaptiveextension again
Private T createadaptiveextension () {try {//return Injectextension (t) getadaptiveextensionclass ().
Newinstance ()); The catch (Exception e) {throw new IllegalStateException ("Can not create adaptive extension" + type + ", Cause:"
+ E.getmessage (), E); }///Custom bytecode instances, such as Protocol$adaptive.class (dynamically generated) or adaptiveextensionfactory (not dynamically generated) private volatile class<?> CAC
Hedadaptiveclass = null;
Private Class<?> Getadaptiveextensionclass () {//emphasis method, get Tpye (Extension point interface) getextensionclasses ();
if (Cachedadaptiveclass!= null) {return cachedadaptiveclass;
return cachedadaptiveclass = Createadaptiveextensionclass (); }//Storage extension point configuration key from extension point profile is the extension Point name Private final holder<map<string, class<?>>> cachedclasses = new H
Older<map<string, class<?>>> (); Gets the Tpye (extension point interface), from the profile read extension point to the cachedclasses cache private map<string, class<?>> getextensionclasses () {M Ap<string, Class<?>> classes = Cachedclasses.get ();
if (classes = = null) {synchronized (cachedclasses) {classes = Cachedclasses.get ();
if (classes = = null) {//read from the configuration file classes = Loadextensionclasses ();
Cachedclasses.set (classes);
}} return classes; The loadextensionclasses read method is no longer parsed, which mainly calls the LoadFile method, mainly from dir = meta-inf/dubbo/internal, meta-inf/dubbo/, meta-inf/
services/read the configuration file sequentially, the filename is dir+ type.getname () such as: Meta-inf/dubbo/internal/com.alibaba.dubbo.rpc.protocol. Ps:loadfile method is very long, mainly done a few things 1. The key is the extension point Name 2 from the configuration file read configuration in map<string,class<?>>. If the extension point class is labeled @Adaptive it treats him as an @adaptive extension implementation (if there are more than one extension point class marked on it that throws an exception) assigns the value to Cachedadaptiveclass. This is not the time to add him to (CONCURRENTMAP<CLASS<?> string> cachednames Storage extension points to the mapping of names) or the Cachedwrapperclasses 3 below. If the extension point class contains a construction method and is passed into the extension point interface, it is placed in the cachedwrapperclasses (private set<class<?>> cachedwrapper) as a wrapper classin Classes;)
Ps: @Adaptive effect: If you mark a class, it means that the class is a custom extension point implementation, such as.
If you mark a method that expands point interfaces, Dubbo dynamically generates an extension point implementation such as: Protocol$adaptive (this class is generated dynamically)
I debug found protocol$adaptive code as follows: Package com.alibaba.dubbo.rpc;
Import Com.alibaba.dubbo.common.extension.ExtensionLoader; public class Protocol$adaptive implements Com.alibaba.dubbo.rpc.Protocol {public void Destroy () {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 () {throw new Unsupportedoperationexception (' method public abstract int Com.alibaba.dubb
O.rpc.protocol.getdefaultport () of interface Com.alibaba.dubbo.rpc.Protocol is not adaptive method! "); 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.i
Nvoker 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) NA
Me from URL ("+ url.tostring () +") to use the 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); Public Com.alibaba.dubbo.rpc.Invoker refer (java.lang.Class arg0, Com.alibaba.dubbo.common.URL arg1) throws Com.alib
aba.dubbo.rpc.RpcException {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 (Extname);
Return Extension.refer (arg0, arg1);
}
}
Extensionfactory Adaptive Class
or then Extensionloader.getextensionloader (extensionfactory.class). Getadaptiveextension () look at the ExtensionFactory. What the self application is.
Through the previous analysis has actually mentioned that is
# Dubbo default provided by the Extensionfactory has the following three
Extensionfactory
Springextensionfactory (com.alibaba.dubbo.config.spring.extension)
Adaptiveextensionfactory (Com.alibaba.dubbo.common.extension.factory)
Spiextensionfactory (Com.alibaba.dubbo.common.extension.factory)
Let's look at the implementation of Adaptiveextensionfactory
Here is actually equivalent to a wrapper class (all extension points are a wrapper class, delegated to specific extension points to provide implementation)//factories to store the specific expansion point//Call GetExtension when the cycle factories get back to the public CLA
SS Adaptiveextensionfactory implements Extensionfactory {private final list<extensionfactory> factories; Public Adaptiveextensionfactory () {extensionloader<extensionfactory> loader = Extensionloader.getextension
Loader (Extensionfactory.class);
list<extensionfactory> list = new arraylist<extensionfactory> (); Loader.getsupportedextensions () Gets the full extension point name (previously said this does not include the adaptive extension point implementation. Cause to see for yourself the com.alibaba.dubbo.common.extension.extensionloader#loadfile is not added to the extensionclasses by the self-applicable extension point for (String n
Ame:loader.getSupportedExtensions ()) {//This is called getextension instead of getadaptiveextension get specific extension points
List.add (loader.getextension (name));
} factories = Collections.unmodifiablelist (list); Public <T> T getextension (class<t> type, String name) {for (E)Xtensionfactory factory:factories) {T extension = factory.getextension (type, name);
if (extension!= null) {return extension;
} return null;
}
}
Get protocol Extension
We analyze the ServiceConfig fragment and see how it initializes the Protocol.
public class Serviceconfig<t> extends Abstractserviceconfig {
private static final long Serialversionuid = 3033 787999037024738L;
private static final Protocol Protocol = Extensionloader.getextensionloader (Protocol.class). Getadaptiveextension ();
The key above is that the Getadaptiveextension method is created and the call stack is as follows:
At Com.alibaba.dubbo.common.extension.ExtensionLoader.createAdaptiveExtensionClass (extensionloader.java:725) At
Com.alibaba.dubbo.common.extension.ExtensionLoader.getAdaptiveExtensionClass (extensionloader.java:720) At
com.alibaba.dubbo.common.extension.ExtensionLoader.createAdaptiveExtension (extensionloader.java:709) At
com.alibaba.dubbo.common.extension.ExtensionLoader.getAdaptiveExtension (extensionloader.java:444)
- Locked <0x32d> (a com.alibaba.dubbo.common.utils.Holder) at
com.alibaba.dubbo.config.serviceconfig.< Clinit> (serviceconfig.java:74) at
Com.alibaba.dubbo.demo.learn1.ServiceExport.main (serviceexport.java:37 )
Because Protocol does not have a default adaptive implementation, Dubbo invokes the Createadaptiveextensionclass method, dynamically generating a class, protocol$adaptive.
The final generation of protocol is an instance of protocol$adaptive.
Protocol$adaptive code is as follows: Package com.alibaba.dubbo.rpc;
Import Com.alibaba.dubbo.common.extension.ExtensionLoader; public class Protocol$adaptive implements Com.alibaba.dubbo.rpc.Protocol {public void Destroy () {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 () {throw new Unsupportedoperationexception (' method public abstract int Com.alibaba.dubb
O.rpc.protocol.getdefaultport () of interface Com.alibaba.dubbo.rpc.Protocol is not adaptive method! "); 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.i
Nvoker 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) NA
Me from URL ("+ url.tostring () +") to use the 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); Public Com.alibaba.dubbo.rpc.Invoker refer (java.lang.Class arg0, Com.alibaba.dubbo.common.URL arg1) throws Com.alib
aba.dubbo.rpc.RpcException {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 () + ") u
SE 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.refer (arg0, arg1);
}
}
PS: Registering URLs
registry://192.168.41.77:2181/com.alibaba.dubbo.registry.registryservice?application=test&dubbo=2.0.0& pid=3428&qos.port=22222®istry=zookeeper×tamp=1523250086375 Summary
So far, the use and loading of extensionloader have been analyzed. Extensionfactory implementation of the self application. And how common extension points such as protocol$adaptive are generated and used.