config-spring module for dubbo source code research

    The dubbo-config-spring module is an Extension of dubbo-config.

    Dubbo's extension point loading is enhanced from the JDK standard SPI (Service Provider Interface) extension point discovery mechanism.
   Dubbo improves the following problems of the JDK standard SPI: The
    JDK standard SPI will instantiate all the implementations of the extension point at one time. If there is an extension implementation, it is time-consuming to initialize, but if it is not used, it will also be loaded, which will waste resources.
    If the extension point fails to load, even the extension point name will not be available. For example: JDK standard ScriptEngine, get the name of the script type through getName();, but if RubyScriptEngine fails to load the RubyScriptEngine class because the jruby.jar it depends on does not exist, the reason for this failure is eaten, and it does not correspond to ruby , when the user executes the ruby ​​script, it will report that ruby ​​is not supported, not the real reason for the failure.
    Added support for extension points IoC and AOP. An extension point can directly inject setters into other extension points.
   Dubbo's spi convention: In the jar package of the extension class, place the extension point configuration file: META-INF/dubbo/interface fully qualified name, the content is: configuration name = extension implementation class fully qualified name, multiple implementation classes use line breaks separated.
  
@SPI
public interface ExtensionFactory {

    /**
     * Get extension.
     *
     * @param type object type.
     * @param name object name.
     * @return object instance.
     */
    <T> T getExtension(Class<T> type, String name);

}

   Dubbo's extension point interface ExtensionFactory, this interface has three

   concrete classes that implement dubbo's extension implementation is ExtensionLoader.
   When the ExtensionLoader loads the extension point, it will check the properties of the extension point (judged by the set method). If the property is the extension point type, the extension point object will be injected. An adaptive extension (a proxy) is injected because it cannot be determined at injection time which extension point is used (determined at use time). When the adaptive extension point is called, a real extension point is selected, and the proxy is used to complete the call. Dubbo selects a real extension point according to the calling method parameters (the information about which extension point is called above).
 
@SuppressWarnings("unchecked")
    private T createExtension(String name) {
        Class<?> clazz = getExtensionClasses().get(name);
        if (clazz == null) {
            throw findException(name);
        }
        try {
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
                EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            injectExtension(instance);
            Set<Class<?>> wrapperClasses = cachedWrapperClasses;
            if (wrapperClasses != null && wrapperClasses.size() > 0) {
                for (Class<?> wrapperClass : wrapperClasses) {
                    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                }
            }
            return instance;
        } catch (Throwable t) {
            throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
                    type + ")  could not be instantiated: " + t.getMessage(), t);
        }
    }
    
    private T injectExtension(T instance) {
        try {
            if (objectFactory != null) {
                for (Method method : instance.getClass().getMethods()) {
                    if (method.getName().startsWith("set")
                            && method.getParameterTypes().length == 1
                            && Modifier.isPublic(method.getModifiers())) {
                        Class<?> pt = method.getParameterTypes()[0];
                        try {
                            String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
                            Object object = objectFactory.getExtension(pt, property);
                            if (object != null) {
                                method.invoke(instance, object);
                            }
                        } catch (Exception e) {
                            logger.error("fail to inject via method " + method.getName()
                                    + " of interface " + type.getName() + ": " + e.getMessage(), e);
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return instance;
    }


   It can be seen that ExtensionLoader holds all extensions of a certain type of extension point, and the extension uses class as the key, and an extension class has only one instance.
  If the extension point uses Adaptive, an adaptive extension class will be generated from the bytecode.
  Return the code of the class through the createAdaptiveExtensionClassCode method, and then return the class object through the Compiler interface
 
  /**
 * Compiler. (SPI, Singleton, ThreadSafe)
 *
 * @author william.liangf
 */
@SPI("javassist")
public interface Compiler {

	/**
	 * Compile java source code.
	 *
	 * @param code Java source code
	 * @param classLoader TODO
	 * @return Compiled class
	 */
	Class<?> compile(String code, ClassLoader classLoader);

}

   Compiler dubbo supports both jdk and Javassist implementations. Pay special attention to the fact that the java version of JdkCompiler is hardcoded to specify the version as 1.6.
   JdkCompiler first generates java files through the JavaFileObject interface, then compiles them into class files through the JavaCompiler interface, and finally loads the generated class files through the ClassLoader.
  -----------------------------Separation line---------------------- ----
  spring namespace extension
  dubbo reads xml configuration by extending spring's namespace.
  dubbo.xsd is an extension file of spring schma. The role is to define related xml elements and namespaces.
  spring.handlers, spring.schemas are the NamespaceHandler and xsd file locations where spring reads the object according to the spi mechanism when parsing xml.
  When many programmers use dubbo to develop, they will find that the ide tool reports an error, because the link to the dubbo namespace on the xml cannot be opened. In fact, this error can be ignored, because the network address when spring parses the xml actually points to the spi configuration file Inside a java class.
  spring.handlers
 
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

   DubboNamespaceHandler registers the parser for related custom elements
 
   
/**
 * DubboNamespaceHandler
 *
 * @author william.liangf
 * @export
 */
public class DubboNamespaceHandler extends NamespaceHandlerSupport {

	static {
		Version.checkDuplicate(DubboNamespaceHandler.class);
	}

	public void init() {
	    registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
        registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
    }

}



Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326565290&siteId=291194637