zoukankan      html  css  js  c++  java
  • 07_dubbo_compiler

    【开始解析最后一行代码 ExtensionLoader.getAdaptiveExtension()】

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

    【getAdaptiveExtension()调用结果】

    ExtesionLoader.getAdaptiveExtension()
    --createAdaptiveExtension()
    ----getAdaptiveExtensionClass()
    //从spi文件中查找实现类上有@Adaptive注解的类
    ------getExtensionClasses()
    --------loadExtensionClasses()
    ----------loadFile(Map<String, Class<?>> extensionClasses, String dir)
    //第三行代码的重点,如果从spi文件中没找到实现类上有@Adaptive的类,则动态创建类
    ------createAdaptiveExtensionClass()

    【 createAdaptiveExtensionClass()源码 】

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

    【createAdaptiveExtensionClassCode()方法 】

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

    【含有@Adaptive注解的方法构造的Protocol$Adaptive对象如下】

    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.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
        }
        public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws com.alibaba.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);
        }
        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.Invoker 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) 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.export(arg0);
        }
    }

    【获取Compiler装饰类】

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

    【com.alibaba.dubbo.common.compiler.Compiler 接口】

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

    adaptive=com.alibaba.dubbo.common.compiler.support.AdaptiveCompiler
    jdk=com.alibaba.dubbo.common.compiler.support.JdkCompiler
    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()。

     getAdaptiveExtension()首先会调用createAdaptiveExtension()创建实例,然后放入缓存,然后返回。

    private T createAdaptiveExtension() {
        try {
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
            throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e);
        }
    }
    private Class<?> getAdaptiveExtensionClass() {
       /**
       * 获取ExtensionClasses和适配类
       * 其中适配类cachedAdaptiveClass如果不存在,则需要使用createAdaptiveExtensionClass()进行创建
       */
      getExtensionClasses();
    if (cachedAdaptiveClass != null) { return cachedAdaptiveClass; } return cachedAdaptiveClass = createAdaptiveExtensionClass(); }

    在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进行属性注入,(AdapviceCompiler必须设置响应的setXxx方法),最后返回AdaptiveCompiler对象实例。

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

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

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

    【AdaptiveCompiler注解】

    /**
     * AdaptiveCompiler. (SPI, Singleton, ThreadSafe)
     *
     * @author william.liangf
     */
    @Adaptive
    public class AdaptiveCompiler implements Compiler {
        //默认编译器的名称
        private static volatile String DEFAULT_COMPILER;
    
        public static void setDefaultCompiler(String compiler) {
            DEFAULT_COMPILER = compiler;
        }
        /**
          * 动态代理,在代理类中,存放着真实对象,使用真实对象执行相应的方法
          */
        public Class<?> compile(String code, ClassLoader classLoader) {
            Compiler compiler;
            ExtensionLoader<Compiler> loader = ExtensionLoader.getExtensionLoader(Compiler.class);
            String name = DEFAULT_COMPILER; // copy reference
            if (name != null && name.length() > 0) {
               //获取名字为name的实现类实例,在获取的过程中会完成IOC和AOP
                compiler = loader.getExtension(name);
            } else {
               //获取默认的javassistCompiler,调用getExtension(cachedDefaultName)
                compiler = loader.getDefaultExtension();
            }
            //根据获取到的实现类Compiler实例,来执行真正的动态生成类的代码
            return compiler.compile(code, classLoader);
        }
    
    }

    【 AbstractCompiler的compile(String code, ClassLoader classLoader)方法】

    /**
     * Abstract compiler. (SPI, Prototype, ThreadSafe)
     *
     * @author william.liangf
     */
    public abstract class AbstractCompiler implements Compiler {
    
        private static final Pattern PACKAGE_PATTERN = Pattern.compile("package\s+([$_a-zA-Z][$_a-zA-Z0-9\.]*);");
    
        private static final Pattern CLASS_PATTERN = Pattern.compile("class\s+([$_a-zA-Z][$_a-zA-Z0-9]*)\s+");
    
        /*
         * 1.根据正则表达式从code中获取包名和类名,组成全类名
         * 2.根据全类名使用Class.forName创建Class<?>,如果该类在jvm中存在,则成功,否则抛ClassNotFoundException异常
         * 3.执行AdaptiveCompiler的doCompile()方法
         */
        public Class<?> compile(String code, ClassLoader classLoader) {
            code = code.trim();
            Matcher matcher = PACKAGE_PATTERN.matcher(code);
            String pkg;
            if (matcher.find()) {
                pkg = matcher.group(1);
            } else {
                pkg = "";
            }
            matcher = CLASS_PATTERN.matcher(code);
            String cls;
            if (matcher.find()) {
                cls = matcher.group(1);
            } else {
                throw new IllegalArgumentException("No such class name in " + code);
            }
            String className = pkg != null && pkg.length() > 0 ? pkg + "." + cls : cls;
            try {
                return Class.forName(className, true, ClassHelper.getCallerClassLoader(getClass()));
            } catch (ClassNotFoundException e) {
                if (!code.endsWith("}")) {
                    throw new IllegalStateException("The java code not endsWith "}", code: 
    " + code + "
    ");
                }
                try {
                    return doCompile(className, code);
                } catch (RuntimeException t) {
                    throw t;
                } catch (Throwable t) {
                    throw new IllegalStateException("Failed to compile class, cause: " + t.getMessage() + ", class: " + className + ", code: 
    " + code + "
    , stack: " + ClassUtils.toString(t));
                }
            }
        }
    
        protected abstract Class<?> doCompile(String name, String source) throws Throwable;
    
    }

    AbstractCompiler的compile(String code, ClassLoader classLoader)方法最终还是会去执行JavassistCompiler的Class<?> doCompiler(String name, String source)方法,在该方法中,使用正则表达式对出传入的源码解析成属性方法等,并使用javassist的API创建Class<?>。

    最后,该

    final Protocol adaptiveExtension = loader.getAdaptiveExtension();

    代码返回的adaptiveExtension = Protocol$Adaptive实例。

    【关于ExtensionLoader的几个方法小结】

    * ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension():
    最终返回的是AdaptiveExtensionFactory实例,其属性factories=[SpringExtensionFactory实例, SpiExtensionFactory实例]
    
    * 不管是获取哪一个SPI接口(除了ExtensionFactory接口)的ExtensionLoader,最终一定会有一个objectFactory = 上述的AdaptiveExtensionFactory实例

    *getAdaptiveExtension():作用是获取一个装饰类或动态代理类,如果有@Adaptive注解的类,则直接返回该类的实例,否则返回一个动态代理类的实例(Protocol$Adaptive的实例),之后完成对实例的IOC属性植入,最后返回实例。
    *getExtension(String key):作用就是从extensionClasses(即指定SPI接口的没有@Adaptive的实现类)获取指定key的extensionClass,并且实例化,之后完成IOC属性注入,之后再进行dubbo-AOP,最后返回实例

    【参考文档】

    https://www.cnblogs.com/java-zhao/p/7469506.html

  • 相关阅读:
    面试题58 二叉树的下一个结点
    面试题57 删除链表中重复的结点
    面试题56 链表中环的入口结点
    面试题55 字符流中第一个不重复的字符
    面试题54 表示数值的字符串
    面试题50 树中两个结点的最低公共祖先
    面试题53 正则表达式匹配
    面试题52 构建乘积数组
    面试题51 数组中重复的数字
    Qt链接库出错version Qt_5 not defined
  • 原文地址:https://www.cnblogs.com/HigginCui/p/9613646.html
Copyright © 2011-2022 走看看