zoukankan      html  css  js  c++  java
  • 5.2 dubbo-compiler源码解析

    1         ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
    2         final Protocol dubboProtocol = loader.getExtension("dubbo");
    3         final Protocol adaptiveExtension = loader.getAdaptiveExtension();

    2.2 dubbo-spi源码解析讲了第一句,在第四章 dubbo内核之aop源码解析讲了第二句,本章来讲最后一句。

    getAdaptiveExtension()层级结构:

    1 ExtensionLoader<T>.getAdaptiveExtension()
    2 --createAdaptiveExtension()
    3 ----injectExtension(getAdaptiveExtensionClass())
    4 ------getAdaptiveExtensionClass()
    5 --------getExtensionClasses()//从spi文件中查找实现类上具有@Adaptive注解的类
    6 ----------loadExtensionClasses()
    7 ------------loadFile(Map<String, Class<?>> extensionClasses, String dir)
    8 --------createAdaptiveExtensionClass()//如果从spi文件中没有找到实现类上具有@Adaptive注解的类,则动态创建类

    这里最后执行到了createAdaptiveExtensionClass()方法。

    1     private Class<?> createAdaptiveExtensionClass() {
    2         String code = createAdaptiveExtensionClassCode();
    3         ClassLoader classLoader = findClassLoader();
    4         com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
    5         return compiler.compile(code, classLoader);
    6     }

    一 构造代码串

    createAdaptiveExtensionClassCode()方法中会判断如果一个类中没有@Adaptive注解的方法,则直接抛出IllegalStateException异常;否则,会为有@Adaptive注解的方法构造代码,而没有@Adaptive注解的方法直接抛出UnsupportedOperationException异常。

    构造出的结果为:

     1 package com.alibaba.dubbo.rpc;
     2 
     3 import com.alibaba.dubbo.common.extension.ExtensionLoader;
     4 
     5 public class Protocol$Adaptive implements com.alibaba.dubbo.rpc.Protocol {
     6     public void destroy() {
     7         throw new UnsupportedOperationException("method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
     8     }
     9     public int getDefaultPort() {
    10         throw new UnsupportedOperationException("method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
    11     }
    12     public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws com.alibaba.dubbo.rpc.RpcException {
    13         if (arg1 == null)
    14             throw new IllegalArgumentException("url == null");
    15         com.alibaba.dubbo.common.URL url = arg1;
    16         String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
    17         if(extName == null)
    18             throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
    19         com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
    20         return extension.refer(arg0, arg1);
    21     }
    22     public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {
    23         if (arg0 == null)
    24             throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
    25         if (arg0.getUrl() == null)
    26             throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
    27         com.alibaba.dubbo.common.URL url = arg0.getUrl();
    28         String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
    29         if(extName == null)
    30             throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
    31         com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
    32         return extension.export(arg0);
    33     }
    34 }

    说明:

    • 该生成类在dubbo2.5.3中export和refer方法声明处的异常抛出是错的(在dubbo2.5.4改正了);
    • 类名在dubbo2.5.4之前(包含2.5.4)也是错的Protocol$Adpative,dubbo2.5.5改正了。

    二 获取Compiler装饰类

    com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();

    先看一下com.alibaba.dubbo.common.compiler.Compiler接口:

    1 @SPI("javassist")
    2 public interface Compiler {
    3     Class<?> compile(String code, ClassLoader classLoader);
    4 }

    @SPI的默认值为javassist,根据上一节的经验,默认获取的Compiler接口的实现类将是META-INF/dubbo/internal/com.alibaba.dubbo.common.compiler.Compiler文件中的key为javassit的实现类。文件内容如下:

    1 adaptive=com.alibaba.dubbo.common.compiler.support.AdaptiveCompiler
    2 jdk=com.alibaba.dubbo.common.compiler.support.JdkCompiler
    3 javassist=com.alibaba.dubbo.common.compiler.support.JavassistCompiler

    根据上一节对ExtensionFactory的getAdaptiveExtension()的讲解,我们最终获取到的Compiler的AdaptiveExtension将是com.alibaba.dubbo.common.compiler.support.AdaptiveCompiler

    来看源码,首先是获取ExtensionLoader<com.alibaba.dubbo.common.compiler.Compiler> loader,最终的loader包含如下属性:

    • Class<?> type = interface com.alibaba.dubbo.common.compiler.Compiler
    • ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
      • factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]

    之后,是loader.getAdaptiveExtension()。

    在该方法中,首先会调用createAdaptiveExtension()创建实例,之后放入缓存,然后返回。

     1     private T createAdaptiveExtension() {
     2         try {
     3             return injectExtension((T) getAdaptiveExtensionClass().newInstance());
     4         } catch (Exception e) {
     5             throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(),
     6                 e);
     7         }
     8     }
     9 
    10     private Class<?> getAdaptiveExtensionClass() {
    11         /**
    12          * 获取ExtensionClasses和适配类
    13          * 其中适配类cachedAdaptiveClass如果不存在,则需要使用createAdaptiveExtensionClass()进行创建.
    14          */
    15         getExtensionClasses();
    16         if (cachedAdaptiveClass != null) {
    17             return cachedAdaptiveClass;
    18         }
    19         return cachedAdaptiveClass = createAdaptiveExtensionClass();
    20     }

    在createAdaptiveExtension()中首先会调用getAdaptiveExtensionClass()获取ExtensionClasses和修饰类,之后将修饰类返回。根据META-INF/dubbo/internal/com.alibaba.dubbo.common.compiler.Compiler文件的内容,最后返回

    • ExtensionClasses
      • "jdk" -> "class com.alibaba.dubbo.common.compiler.support.JdkCompiler"
      • "javassist" -> "class com.alibaba.dubbo.common.compiler.support.JavassistCompiler"
    • cachedAdaptiveClass=class com.alibaba.dubbo.common.compiler.support.AdaptiveCompiler

    之后调用AdaptiveCompiler的无参构造器创建AdaptiveCompiler对象实例,然后执行injectExtension(T instance)(这里没起作用)为AdaptiveCompiler对象实例注入相应的属性(AdaptiveCompiler必须提供相应的setter方法),最后返回AdaptiveCompiler对象实例。

    三 编译代码并加载为Class<?>对象

    创建好AdaptiveCompiler对象实例之后,然后执行下面的方法。

    Class<?> compile(String code, ClassLoader classLoader)

    看一下AdaptiveCompiler全部源码:

     1 @Adaptive
     2 public class AdaptiveCompiler implements Compiler {
     3     private static volatile String DEFAULT_COMPILER;//默认的编译器的名字
     4 
     5     public static void setDefaultCompiler(String compiler) {
     6         DEFAULT_COMPILER = compiler;
     7     }
     8 
     9     /**
    10      * 典型的动态代理,在代理类中,存放着真实对象,使用真实对象执行相应的方法
    11      */
    12     public Class<?> compile(String code, ClassLoader classLoader) {
    13         Compiler compiler;
    14         ExtensionLoader<Compiler> loader = ExtensionLoader.getExtensionLoader(Compiler.class);
    15         String name = DEFAULT_COMPILER; // copy reference
    16         if (name != null && name.length() > 0) {
    17             compiler = loader.getExtension(name);//获取名字为name的实现类的实例,在获取的过程中会完成IOC和AOP
    18         } else {
    19             compiler = loader.getDefaultExtension();//获取默认的JavassitCompiler,调用getExtension(cachedDefaultName)
    20         }
    21         return compiler.compile(code, classLoader);//根据获取到的实现类compiler实例,来执行真正的动态生成类的代码
    22     }
    23 }

    这里执行的是compiler = loader.getDefaultExtension(),该方法不说了,就是调用了getExtension(cachedDefaultName)生成一个JavassistCompiler的实例。之后就是执行JavassistCompiler的compile(String code, ClassLoader classLoader)方法。

     1 package com.alibaba.dubbo.common.compiler.support;
     2 
     3 import com.alibaba.dubbo.common.compiler.Compiler;
     4 import com.alibaba.dubbo.common.utils.ClassHelper;
     5 
     6 import java.util.regex.Matcher;
     7 import java.util.regex.Pattern;
     8 
     9 /**
    10  * Abstract compiler. (SPI, Prototype, ThreadSafe)
    11  */
    12 public abstract class AbstractCompiler implements Compiler {
    13     private static final Pattern PACKAGE_PATTERN = Pattern.compile("package\s+([$_a-zA-Z][$_a-zA-Z0-9\.]*);");
    14     private static final Pattern CLASS_PATTERN = Pattern.compile("class\s+([$_a-zA-Z][$_a-zA-Z0-9]*)\s+");
    15 
    16     /**
    17      * 1 根据正则表达式从code中获取包名和类名,组成全类名
    18      * 2 根据全类名使用Class.forName创建Class<?>,如果该类在jvm中存在,则成功,否则抛出ClassNotFoundException,
    19      *   执行doCompile方法。
    20      */
    21     public Class<?> compile(String code, ClassLoader classLoader) {
    22         code = code.trim();
    23         Matcher matcher = PACKAGE_PATTERN.matcher(code);
    24         String pkg;
    25         if (matcher.find()) {
    26             pkg = matcher.group(1);
    27         } else {
    28             pkg = "";
    29         }
    30         matcher = CLASS_PATTERN.matcher(code);
    31         String cls;
    32         if (matcher.find()) {
    33             cls = matcher.group(1);
    34         } else {
    35             throw new IllegalArgumentException("No such class name in " + code);
    36         }
    37         String className = pkg != null && pkg.length() > 0 ? pkg + "." + cls : cls;
    38         try {
    39             return Class.forName(className, true, ClassHelper.getCallerClassLoader(getClass()));
    40         } catch (ClassNotFoundException e) {
    41             if (!code.endsWith("}")) {
    42                 throw new IllegalStateException("The java code not endsWith "}", code: 
    " + code + "
    ");
    43             }
    44             try {
    45                 return doCompile(className, code);
    46             } catch (RuntimeException t) {
    47                 throw t;
    48             } catch (Throwable t) {
    49                 throw new IllegalStateException("Failed to compile class, cause: " + t.getMessage() + ", class: " + className + ", code: 
    " + code + "
    , stack: " + ClassUtils.toString(t));
    50             }
    51         }
    52     }
    53 
    54     protected abstract Class<?> doCompile(String name, String source) throws Throwable;
    55 }

    该方法会执行JavassistCompiler的Class<?> doCompile(String name, String source)方法了,在该方法中,使用正则表达式对传入的源码解析成属性方法等,并使用javassist的API创建Class<?>。

    最后,该final Protocol adaptiveExtension = loader.getAdaptiveExtension();代码返回的adaptiveExtension = Protocol$Adaptive实例。

    总结(再啰嗦一遍):

    • ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()最终返回的是:AdaptiveExtensionFactory实例,其属性factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]
    • 不管是获取哪一个SPI接口(除了ExtensionFactory.接口)的ExtensionLoader,最终一定会有一个objectFactory=上述的AdaptiveExtensionFactory实例
    • getAdaptiveExtension():作用就是获取一个装饰类或动态代理类的实例, 如果有@Adaptive注解的类,则直接返回该类的实例,否则返回一个动态代理类的实例(例如Protocol$Adaptive的实例),之后完成属性注入(dubbo-IOC),最后返回实例。
    • getExtension(String key):作用就是从extensionClasses(即指定SPI接口的没有@Adaptive的实现类)获取指定key的extensionClass,并且实例化,之后完成属性注入(dubbo-IOC),再之后完成dubbo-AOP,最后返回实例。
  • 相关阅读:
    STL next_permutation 全排列
    日期问题
    兰顿蚂蚁
    矩阵翻硬币
    数学问题-排列组合
    h5css3_03练习
    h5css3_03
    h5css3_02练习
    h5css3_02
    h5c3_01练习
  • 原文地址:https://www.cnblogs.com/java-zhao/p/7469506.html
Copyright © 2011-2022 走看看