Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Introduction to the SPI mechanism of Dubbo and the method of loading class by SPI

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly explains the "introduction of the SPI mechanism of Dubbo and the method of loading class by SPI". The content of the explanation in the article is simple and clear, and it is easy to learn and understand. please follow the editor's train of thought to study and learn "the introduction of the SPI mechanism of Dubbo and the method of loading class by SPI".

1. SPI example of Dubbo @ SPIpublic interface Robot {void sayHello ();} public class OptimusPrime implements Robot {@ Override public void sayHello () {System.out.println ("Hello, I am Optimus Prime.");}} public class Bumblebee implements Robot {@ Override public void sayHello () {System.out.println ("Hello, I am Bumblebee.") }} public class DubboSPITest {@ Test public void sayHelloDubbo () throws Exception {ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader (Robot.class); Robot optimusPrime = extensionLoader.getExtension ("optimusPrime"); optimusPrime.sayHello (); Robot bumblebee = extensionLoader.getExtension ("bumblebee"); bumblebee.sayHello ();} output: SPI source code analysis of Hello, I am Optimus Prime.Hello, I am Bumblebee.2, Dubbo ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader (Robot.class) Public static ExtensionLoader getExtensionLoader (Class type) {if (type = = null) throw new IllegalArgumentException ("Extension type = = null"); if (! type.isInterface ()) {throw new IllegalArgumentException ("Extension type (" + type + ") is not interface!") } if (! withExtensionAnnotation (type)) {throw new IllegalArgumentException ("Extension type (" + type + ") is not extension, because WITHOUT @" + SPI.class.getSimpleName () + "Annotation!");} / / get the ExtensionLoader ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOADERS.get (type) corresponding to the extension class from the cache If (loader = = null) {/ / if cache misses, create a new instance. Take a brief look at new ExtensionLoader (type) EXTENSION_LOADERS.putIfAbsent (type, new ExtensionLoader (type)); loader = (ExtensionLoader) EXTENSION_LOADERS.get (type);} return loader;}

For the creation of objectFactory here, please refer to Dubbo's SPI mechanism to analyze 3-Dubbo 's IOC dependency injection.

Private ExtensionLoader (Class type) {this.type = type; / / where type is Robot.class, so the following code is executed, loading and creating SpiExtensionFactory and SpringExtensionFactory, objectFactory = (type = = ExtensionFactory.class? Null: ExtensionLoader.getExtensionLoader (ExtensionFactory.class). GetAdaptiveExtension ();} Robot optimusPrime = extensionLoader.getExtension ("optimusPrime"); public T getExtension (String name) {if ("true" .equals (name)) {return getDefaultExtension ();} / / Holder is also used to hold objects, as cache Holder holder = cachedInstances.get (name) If (holder = = null) {cachedInstances.putIfAbsent (name, new Holder ()); holder = cachedInstances.get (name);} Object instance = holder.get (); if (instance = = null) {synchronized (holder) {instance = holder.get () If (instance = = null) {/ / create an extension instance. Analyze createExtension (name) instance = createExtension (name); holder.set (instance);}} return (T) instance;}

Here, we can refer to Dubbo's SPI mechanism to analyze 3-Dubbo 's IOC dependency injection.

Private T createExtension (String name) {/ / load all the extension classes from the configuration file, you can get the mapping table from "configuration item name" to "configuration class" / / get it according to name after loading, get getExtensionClasses () like com.alibaba.dubbo.demo.provider.spi.OptimusPrime / / focus on analysis later, and delete some non-key codes Class clazz = getExtensionClasses (). Get (name) Try {/ / also attempts to get it from the cache first, but cannot get one created by reflection and put into the cache T instance = (T) EXTENSION_INSTANCES.get (clazz); if (instance = = null) {EXTENSION_INSTANCES.putIfAbsent (clazz, clazz.newInstance ()); instance = (T) EXTENSION_INSTANCES.get (clazz) } / / dependency injection and cachedWrapperClasses, followed by injectExtension (instance); Set > getExtensionClasses () {/ / get mapping table Map > loadExtensionClasses () {/ / get SPI annotations from cache, where type is the final SPI defaultAnnotation = type.getAnnotation (SPI.class) passed in when calling the getExtensionLoader method; if (defaultAnnotation! = null) {String value = defaultAnnotation.value () If ((value = value.trim ()) .length () > 0) {String [] names = NAME_SEPARATOR.split (value) If (names.length > 1) {/ / throw exception} / / get the value in @ SPI annotation and cache it. You can follow it. Later you will use if (names.length = = 1) cachedDefaultName = names [0];}} Map > () / / load the configuration files under the specified folder, META-INF/services/, META-INF/dubbo/, META-INF/dubbo/internal/ loadDirectory (extensionClasses, DUBBO_INTERNAL_DIRECTORY); / / I put loadDirectory (extensionClasses, DUBBO_DIRECTORY) in this directory; loadDirectory (extensionClasses, SERVICES_DIRECTORY); return extensionClasses } private void loadDirectory (Map > extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {try {BufferedReader reader = new BufferedReader (new InputStreamReader (resourceURL.openStream (), "utf-8")); try {String line; / / read configuration while ((line = reader.readLine ())! = null) {final int ci = line.indexOf ('#') / / locate the # character, followed by a comment, skip if (ci > = 0) line = line.substring (0, ci); line = line.trim (); if (line.length () > 0) {try {String name = null / cut int I = line.indexOf ('=') by equal sign; if (I > 0) {name = line.substring (0, I). Trim (); line = line.substring (I + 1). Trim () } if (line.length () > 0) {/ / the real unloading class loadClass (extensionClasses, resourceURL, Class.forName (line, true, classLoader), name) }}}

Label 1, here can refer to: Dubbo SPI mechanism analysis 2-Adaptive detailed explanation

Note 2, here can refer to: Dubbo's SPI mechanism analysis 4-Dubbo implements AOP through Wrapper

Label 3, the cachedActivates here can refer to: Dubbo's SPI mechanism analysis 5-Activate detailed explanation

Private void loadClass (Map clazz, String name) throws NoSuchMethodException {/ / clazz must be of type type, otherwise, throw an exception if (! type.isAssignableFrom (clazz)) {} / / determine whether clazz is marked with @ Adaptive annotation, label 1 if (clazz.isAnnotationPresent (Adaptive.class)) {if (cachedAdaptiveClass = = null) {cachedAdaptiveClass = clazz } else if (! cachedAdaptiveClass.equals (clazz)) {/ / throw an exception. There cannot be multiple classes marked with @ Adaptive annotation}} / / to determine whether it is of Wrapper type. Label 2 else if (isWrapperClass (clazz)) {Set > (); wrappers = cachedWrapperClasses;} wrappers.add (clazz) } / / the program enters this branch, indicating that clazz is a common extension class, and Robot is a common extension class else {/ / check whether clazz has a default construction method, and if not, throw an exception clazz.getConstructor (); if (name = = null | | name.length () = 0) {name = findAnnotationName (clazz) If (name.length () = = 0) {/ / throw exception}} String [] names = NAME_SEPARATOR.split (name); if (names! = null & & names.length > 0) {/ / for @ Activate conditional activation, label 3 Activate activate = clazz.getAnnotation (Activate.class) If (activate! = null) {cachedActivates.put (names [0], activate);} for (String n: names) {if (! cachedNames.containsKey (clazz)) {cachedNames.put (clazz, n);} Class c = extensionClasses.get (n) If (c = = null) {/ / stores the mapping of names to class, so that a line of extensionClasses.put (n, clazz) is parsed } else if (c! = clazz) {/ / throw exception} Thank you for reading. This is the introduction of SPI mechanism of Dubbo and the method of loading class by SPI. After the study of this article, I believe that you have a deeper understanding of the introduction of the SPI mechanism of Dubbo and the method of loading class in SPI, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report