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 of SPI mechanism of Dubbo and IOC dependency injection example of Dubbo

2025-02-23 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 SPI mechanism of Dubbo and the example of IOC dependency injection of Dubbo". The content of the explanation in this 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 Dubbo's SPI mechanism and Dubbo's IOC dependency injection example".

1. IOC example of Dubbo @ Testpublic void test1 () {ExtensionLoader loader = ExtensionLoader.getExtensionLoader (AdaptiveExt.class); AdaptiveExt adaptiveExtension = loader.getExtension ("dubbo"); URL url = URL.valueOf ("test://localhost/test"); adaptiveExtension.echo ("d", url);} public class DubboAdaptiveExt implements AdaptiveExt {/ / dubbo has a variable private AdaptiveExt adaptiveExt; public void setAdaptiveExt (AdaptiveExt adaptiveExt) that depends on AdaptiveExt type {this.adaptiveExt = adaptiveExt } @ Override public String echo (String msg, URL url) {System.out.println (this.adaptiveExt.echo (msg, url)); return "dubbo";} / / at this time ThriftAdaptiveExt is @ Adaptivepublic class ThriftAdaptiveExt implements AdaptiveExt {@ Override public String echo (String msg, URL url) {return "thrift" marked with @ Adaptive annotation;}} 2. ExtensionFactory needed for Dubbo's IOC

In the IOC of Spring, injecting dependency to the generated bean is similar to calling context.getBean (name) to get the IOC of the bean.Dubbo to be injected. It uses the variable objectFactory of type ExtensionFactory to get the bean in dubbo, and the core code objectFactory.getExtension (pt, property). Let's first analyze the process of creating objectFactory. ObjectFactory needs to use SpringExtensionFactory and SpiExtensionFactory. First take a look at the ExtenionFactory implementation class, as shown in the following figure. The following through the source code analysis of the generation process of objectFactory.

For a detailed analysis of getExtensionLoader () here, please refer to Dubbo's SPI mechanism analysis 1-SPI loading class

ExtensionLoader loader = ExtensionLoader.getExtensionLoader (AdaptiveExt.class); public static ExtensionLoader getExtensionLoader (Class type) {/ / delete some unnecessary code. For more information, please see the previous analysis / / 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 and create a new instance using EXTENSION_LOADERS.putIfAbsent (type, new ExtensionLoader (type)); loader = (ExtensionLoader) EXTENSION_LOADERS.get (type);} return loader;} private ExtensionLoader (Class type) {this.type = type / / the type here is AdaptiveExt.class, so the following code is executed, loading and creating SpiExtensionFactory and SpringExtensionFactory objectFactory = (type = = ExtensionFactory.class? Null: ExtensionLoader.getExtensionLoader (ExtensionFactory.class). GetAdaptiveExtension ();} public T getAdaptiveExtension () {Object instance = cachedAdaptiveInstance.get (); if (instance = = null) {if (createAdaptiveInstanceError = = null) {synchronized (cachedAdaptiveInstance) {instance = cachedAdaptiveInstance.get () If (instance = = null) {try {/ / create an adaptive extension proxy class object and put it into the cache. What is created here is ExtensionFactory's adaptive extension object instance = createAdaptiveExtension (); cachedAdaptiveInstance.set (instance) } catch (Throwable t) {/ / throw exception}} return (T) instance } private T createAdaptiveExtension () {try {/ / is divided into three steps: 1 is to create adaptive extension agent class Class objects, 2 is to create objects through reflection, 3 is to inject return injectExtension ((T) getAdaptiveExtensionClass (). NewInstance ()) into the created objects on-demand dependency;} catch (Exception e) {/ / throw exception}}

For a detailed analysis of the getExtensionClasses () method, please see: SPI Mechanism Analysis of Dubbo 1-SPI loading class

Private Class getAdaptiveExtensionClass () {/ / has been analyzed in the previous article. It will load three implementation classes of ExtensionFactory in the default directory. The directory is / / META-INF/dubbo/internal/,. The directory corresponds to two files. The contents of the files are shown below. Because AdaptiveExtensionFactory is annotated with @ Adaptive, it has the highest priority. It is the default implementation class getExtensionClasses () of ExtensionFactory. / / if the @ Adaptive annotation implementation class is marked, then cachedAdaptiveClass is not empty, return if (cachedAdaptiveClass! = null) {/ / return directly here, cachedAdaptiveClass = AdaptiveExtensionFactory.class return cachedAdaptiveClass;} / / will not take this step return cachedAdaptiveClass = createAdaptiveExtensionClass () } File 1 content: / / where AdaptiveExtensionFactory is marked with @ Adaptive comment adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactoryspi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory file 2 content: spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory@Adaptivepublic class AdaptiveExtensionFactory implements ExtensionFactory {/ / after analyzing getAdaptiveExtensionClass (), it returns AdaptiveExtensionFactory, and then newInstance will call its default constructor return injectExtension ((T) getAdaptiveExtensionClass (). NewInstance ()). @ Adaptivepublic class AdaptiveExtensionFactory implements ExtensionFactory {/ / maintain SpringExtensionFactory and SpiExtensionFactory private final List factories; public AdaptiveExtensionFactory () {ExtensionLoader loader = ExtensionLoader.getExtensionLoader (ExtensionFactory.class); List list = new ArrayList () For (String name: loader.getSupportedExtensions ()) {/ / create objects for SpringExtensionFactory and SpiExtensionFactory respectively and put them into list list.add (loader.getExtension (name));} factories = Collections.unmodifiableList (list) }} 3. IOC source code analysis of Dubbo / / the first line of code has been analyzed above, in which a variable objectFactory of type ExtensionFactory is created, in which an instance of list,// list with SpringExtensionFactory and SpiExtensionFactory types is maintained. Dubbo's IOC obtains bean through these two variables to obtain ExtensionLoader loader = ExtensionLoader.getExtensionLoader (AdaptiveExt.class); AdaptiveExt adaptiveExtension = loader.getExtension ("dubbo") Public T getExtension (String name) {/ / remove some code if (instance = = null) {synchronized (holder) {instance = holder.get (); if (instance = = null) {/ / create an extension instance instance = createExtension (name); holder.set (instance) } return (T) instance } private T createExtension (String name) {/ / load all the extension classes from the configuration file to get the mapping table from "configuration item name" to "configuration class" / / here we specify the name dubbo, not through the getAdaptiveExtension method to obtain the adaptive extension class, which needs to be distinguished / / so what we get here is com.alibaba.dubbo.demo.provider.adaptive.impl.DubboAdaptiveExt Class clazz = getExtensionClasses (). Get (name) If (clazz = = null) {throw findException (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) {/ / here create an instance of DubboAdaptiveExt directly through reflection, and then give him dependency injection EXTENSION_INSTANCES.putIfAbsent (clazz, clazz.newInstance ()); instance = (T) EXTENSION_INSTANCES.get (clazz);} / dependency injection injectExtension (instance); return instance } private T injectExtension (T instance) {/ / here to look good in typesetting, delete some exception catch and throw code / / objectFactory that we analyzed earlier, which maintains all the methods of if (objectFactory! = null) {/ / traversing DubboAdaptiveExt instances of SpringExtensionFactory and SpiExtensionFactory types, looking for the beginning of set with a parameter of 1 Method for (Method method: instance.getClass (). GetMethods ()) {if (method.getName (). StartsWith ("set") & & method.getParameterTypes (). Length = = 1 & & Modifier.isPublic (method.getModifiers () {/ / get the parameter type Here is AdaptiveExt.class Class pt = method.getParameterTypes () [0] / / get the attribute name, here is adaptiveExt String property = method.getName () .length () > 3? Method.getName () .substring (3,4) .toLowerCase () + method.getName () .substring (4): ""; / / get the instance of AdaptiveExt.class type in the container named adaptiveExt Object object = objectFactory.getExtension (pt, property); / / assign if (object! = null) {method.invoke (instance, object) through reflection after getting } return instance;} @ Adaptivepublic class AdaptiveExtensionFactory implements ExtensionFactory {private final List factories; @ Override public T getExtension (Class type, String name) {/ / traverses all the ExtensionFactory in factory. Get it from SpiExtensionFactory first, but not get for (ExtensionFactory factory: factories) {T extension = factory.getExtension (type, name) in the Spring container. If (extension! = null) {return extension;}} return null;}}

For the adaptive extension here, please refer to Dubbo's SPI mechanism analysis 2-Adaptive.

Public class SpiExtensionFactory implements ExtensionFactory {@ Override public T getExtension (Class type, String name) {if (type.isInterface () & & type.isAnnotationPresent (SPI.class)) {ExtensionLoader loader = ExtensionLoader.getExtensionLoader (type) If (! loader.getSupportedExtensions (). IsEmpty ()) {/ / first see how to get SpiExtensionFactory. It is acquired adaptively through getAdaptiveExtension (), and name is not used at all, so here returns the instance of ThriftAdaptiveExt return loader.getAdaptiveExtension ();}} return null }} public class SpringExtensionFactory implements ExtensionFactory {/ / you can see that Spring is first fetched according to the name, and then @ Override public T getExtension (Class type, String name) {for (ApplicationContext context: contexts) {if (context.containsBean (name)) {Object bean = context.getBean (name) If (type.isInstance (bean)) {return (T) bean;} for (ApplicationContext context: contexts) {try {return context.getBean (type);}} return null }} / / so this code outputs: thrift@Testpublic void test1 () {ExtensionLoader loader = ExtensionLoader.getExtensionLoader (AdaptiveExt.class); AdaptiveExt adaptiveExtension = loader.getExtension ("dubbo"); URL url = URL.valueOf ("test://localhost/test"); adaptiveExtension.echo ("d", url) 4. The test comments out the comments above the ThriftAdaptiveExt class through URL dependency injection / * test, and annotates the AdaptiveExt method with @ Adaptive ("t") * / @ Testpublic void test5 () {ExtensionLoader loader = ExtensionLoader.getExtensionLoader (AdaptiveExt.class); Map map = new HashMap () / / t this key is based on @ Adaptive ("t"), and the two should be consistent with map.put ("t", "cloud"); URL url = new URL ("", ", 1, map); AdaptiveExt adaptiveExtension = loader.getExtension (" dubbo "); adaptiveExtension.echo (", url);}

The above code outputs spring cloud, and when an instance of DubboAdaptiveExt is created to inject dependencies, injectExtension (instance) is called. Since there is no class marked with @ Adaptive, Dubbo needs to generate its own adaptive extension proxy class Class. For more information on the generation process, please refer to the SPI mechanism analysis and 2-Adaptive explanation of Dubbo. There is a key code in the generated proxy class: String extName = url.getParameter ("t", "dubbo"). Because there is this t parameter in url, the echo method of SpringCloudAdaptiveExt corresponding to cloud is finally called to output spring cloud.

Thank you for reading, the above is the "introduction of Dubbo's SPI mechanism and Dubbo's IOC dependency injection example". After the study of this article, I believe you have a deeper understanding of the introduction of Dubbo's SPI mechanism and Dubbo's IOC dependency injection instance, and the specific use still 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