Dubbo源码(2)-动态编译技术源码解析

精尽 Dubbo 源码分析 —— 动态代理(一)之 Javassist 1.概述 在 《Dubbo 用户指南 —— schema 配置参考手册》 中,我们可以看到 <dubbo:service /> 和 <dubbo:reference /> 标签中,可以通过 “proxy” 属性,可以配置动态代理的生成方式: 生成动态代理方式,可选:jdk / javassist 2.整体流程 在 Consumer 中,我们调用 Service 接口的方法... 阅读详情

本文主要参考自Dubbo官方文档、Dubbo项目源码以及网络文章和相关书籍,并附上自身的一些理解,如有遗漏或错误,还望海涵并指出。谢谢!

------本文基于Dubbo-2.6.1版本

一.Javassist动态编译

1.1、Javassist介绍

Javassist是一款Java字节码生成和转化框架,它在Dubbo中起到的作用是动态编译以及动态代理。

为什么需要使用Javassist作为动态编译和代理框架呢,原因主要Javassist的性能以及效率都高于JDK自身的框架。

譬如,如果需要在运行期获取一个特定的类可以采用JDK反射来实现,但是使用反射会有一个缺点—效率低,所以在一些追求效率的场合会使用Javassist直接在内存中生成class字节码对象供程序来使用,这就是Dubbo使用Javassist的原因。

1.2、入门使用

下面编写一个入门Demo来演示一下如何使用Javassist在内存中生成一个class,并且将其字节码输出到文件中保存起来:

  • TestJavassist
@Test
    public void test_Javassist() throws CannotCompileException, NotFoundException, IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        ClassPool pool = ClassPool.getDefault();
        CtClass cls = pool.makeClass("thinking_in_java.javassist.proxyClass");
        // 添加私有成员name及其getter、setter方法
        CtField param = new CtField(pool.get("java.lang.String"), "name", cls);
        param.setModifiers(Modifier.PRIVATE);
        cls.addMethod(CtNewMethod.setter("setName", param));
        cls.addMethod(CtNewMethod.getter("getName", param));
        cls.addField(param, CtField.Initializer.constant(""));

        // 添加无参的构造体
        CtConstructor cons = new CtConstructor(new CtClass[] {}, cls);
        cons.setBody("{name = \"ARong\";}");
        cls.addConstructor(cons);

        // 添加有参的构造体
        cons = new CtConstructor(new CtClass[] {pool.get("java.lang.String")}, cls);
        cons.setBody("{$0.name = $1;}");
        cls.addConstructor(cons);

        // 打印创建类的类名
        System.out.println(cls.toClass());
        // 输出字节码到class中
        byte[] bytes = cls.toBytecode();
        FileOutputStream fos = new FileOutputStream(new File("/Users/arong/MyFile/Project/Algorithm/src/main/java/thinking_in_java/javassist/proxyClass.class"));
        fos.write(bytes);
        fos.flush();
        Object o = Class.forName("thinking_in_java.javassist.proxyClass").newInstance();
        Method getName = o.getClass().getMethod("getName");
        Object res = getName.invoke(o);
        System.out.println(o);
        System.out.println(res);
    }

输出:

class thinking_in_java.javassist.proxyClass
thinking_in_java.javassist.proxyClass@dfd3711
ARong

在文件夹中查看生成的class字节码文件(idea自动反编译成了Java代码):

  • proxyClass.class
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package thinking_in_java.javassist;

public class proxyClass {
    private String name = "";

    public void setName(String var1) {
        this.name = var1;
    }

    public String getName() {
        return this.name;
    }

    public proxyClass() {
        this.name = "ARong";
    }

    public proxyClass(String var1) {
        this.name = var1;
    }
}

二.Dubbo动态编译源码解析

看完了Javassist,我们大概知道其实这个框架的作用就是为了代替反射,用更高效的方式直接在内存中生成所需的class。

在Dubbo中也大量地使用了Javassist来做动态编译,譬如在SPI机制中的核心类ExtensionLoader中的生成自适应拓展实现类的createAdaptiveExtensionClass方法就使用了动态编译来生成适应类,不过Dubbo基于Javassist做了一层封装:

  • ExtensionLoader
/*
    *   创建自适应拓展类的代码并进行编译返回,生成Xxx$Adaptive自适应类(动态编译)
     */
    private Class<?> createAdaptiveExtensionClass() {
        // 生成自适应类的代码字符串
        String code = createAdaptiveExtensionClassCode();
        // 获取ClassLoader
        ClassLoader classLoader = findClassLoader();
        // 对代码进行编译,生成相应的Class返回
        com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
        return compiler.compile(code, classLoader);
    }
3.1、createAdaptiveExtensionClassCode方法

在这个方法中生成了Xxx&Adaptive自适应实现类的代码字符串,可供后续被Dubbo编译成真正的Class类:

  • createAdaptiveExtensionClassCode
/*
    *   生成自适应拓展类的代码
     */
    private String createAdaptiveExtensionClassCode() {
        // 使用StringBuilder来构建代码字符串
        StringBuilder codeBuidler = new StringBuilder();
        // 检测方法上是否含有@Adaptive注解,不含有则抛出异常
        Method[] methods = type.getMethods();
        boolean hasAdaptiveAnnotation = false;
        for (Method m : methods) {
            if (m.isAnnotationPresent(Adaptive.class)) {
                hasAdaptiveAnnotation = true;
                break;
            }
        }
        // no need to generate adaptive class since there's no adaptive method found.
        if (!hasAdaptiveAnnotation)
            throw new IllegalStateException("No adaptive method on extension " + type.getName() + ", refuse to create the adaptive class!");
        // 开始构建package、import内容以及类名(Xxx$Adaptive)
        codeBuidler.append("package " + type.getPackage().getName() + ";");
        codeBuidler.append("\nimport " + ExtensionLoader.class.getName() + ";");
        codeBuidler.append("\npublic class " + type.getSimpleName() + "$Adaptive" + " implements " + type.getCanonicalName() + " {");
        //  生成代理所含有的方法
        // 省略...
        return codeBuidler.toString();
    }

想更深入地了解具体的代码生成逻辑可以看官方文档关于这个方法的解析:
https://dubbo.apache.org/zh-cn/docs/source_code_guide/adaptive-extension.html

在执行完这个方法之后,就会生成一个自适应拓展类的Java代码字符串了,类似于下面这个形式:

  • Ext2$Adaptive
package com.alibaba.dubbo.common.extensionloader.ext2;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Ext2$Adaptive implements com.alibaba.dubbo.common.extensionloader.ext2.Ext2 {
public java.lang.String bang(com.alibaba.dubbo.common.URL arg0, int arg1) {throw new UnsupportedOperationException("method public abstract java.lang.String com.alibaba.dubbo.common.extensionloader.ext2.Ext2.bang(com.alibaba.dubbo.common.URL,int) of interface com.alibaba.dubbo.common.extensionloader.ext2.Ext2 is not adaptive method!");
}
public java.lang.String echo(com.alibaba.dubbo.common.extensionloader.ext2.UrlHolder arg0, java.lang.String arg1) {
if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.common.extensionloader.ext2.UrlHolder argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.common.extensionloader.ext2.UrlHolder argument getUrl() == null");com.alibaba.dubbo.common.URL url = arg0.getUrl();
String extName = url.getParameter("ext2");
if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.common.extensionloader.ext2.Ext2) name from url(" + url.toString() + ") use keys([ext2])");
com.alibaba.dubbo.common.extensionloader.ext2.Ext2 extension = (com.alibaba.dubbo.common.extensionloader.ext2.Ext2)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.extensionloader.ext2.Ext2.class).getExtension(extName);
return extension.echo(arg0, arg1);
}
}
3.2、Compiler接口

接下来就是重点了:如何将Java代码字符串编译成可供使用的Class?如下面的代码:

  • ExtensionLoader
/*
    *   创建自适应拓展类的代码并进行编译返回,生成Xxx$Adaptive自适应类(动态编译)
     */
    private Class<?> createAdaptiveExtensionClass() {
        // 生成自适应类的代码字符串
        String code = createAdaptiveExtensionClassCode();
        // 获取ClassLoader
        ClassLoader classLoader = findClassLoader();
        // 对代码进行编译,生成相应的Class返回
        com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
        return compiler.compile(code, classLoader);
    }

这就是Complier接口做的事情,Complier接口的全限定名:

com.alibaba.dubbo.common.compiler.Compiler
  • Compiler
@SPI("javassist")
public interface Compiler {

    /**
     * Compile java source code.
     *
     * 编译 Java 代码字符串
     *
     * @param code        Java source code
     *                    Java 代码字符串
     * @param classLoader classloader
     *                    类加载器
     * @return Compiled class
     *                    编译后的类
     */
    Class<?> compile(String code, ClassLoader classLoader);
}

可以看出Compiler接口也是使用了SPI机制的,其默认拓展实现类为javassist这个拓展名映射的实现类,
查阅resource/META-INF/dubbo查看Compiler接口所有拓展实现类:

  • META-INF/dubbo/internal/com.alibaba.dubbo.common.compiler.Compiler
adaptive=com.alibaba.dubbo.common.compiler.support.AdaptiveCompiler
jdk=com.alibaba.dubbo.common.compiler.support.JdkCompiler
javassist=com.alibaba.dubbo.common.compiler.support.JavassistCompiler

在这里插入图片描述

有效代码量750行左右:

在这里插入图片描述

3.2.1、AdaptiveCompiler

com.alibaba.dubbo.common.compiler.support.AdaptiveCompiler ,实现 Compiler 接口,自适应 Compiler 实现类。

  • AdaptiveComiler
@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
        ExtensionLoader<Compiler> loader = ExtensionLoader.getExtensionLoader(Compiler.class);
        // 编译器名称设置为默认
        String name = DEFAULT_COMPILER; // copy reference
        if (name != null && name.length() > 0) {
            // 使用指定的编译器
            compiler = loader.getExtension(name);
        } else {
            // 使用默认编译器(Javassist)
            compiler = loader.getDefaultExtension();
        }
        // 编译生成Class
        return compiler.compile(code, classLoader);
    }
}

从AdaptiveCompiler的代码中可以看出,获取到自适应的Compiler,默认情况下也是获取到Javassist作为拓展实现的,当然也可以指定其他实现,譬如JDK。

如果需要指定JDK Compiler,可通过下述配置:

<dubbo:application compiler="jdk" />

这个配置会触发ApplicationConfig的setCompiler方法,该方法会调用setDefaultCompiler设置编译器:

  • ApplicationConfig
public void setCompiler(String compiler) {
    this.compiler = compiler;
    AdaptiveCompiler.setDefaultCompiler(compiler);
}
3.2.2、AbstractCompiler

com.alibaba.dubbo.common.compiler.support.AbstractCompiler是Compiler接口的实现类,使用模板方法模式,定义doCompile方法,实质上依赖于JavassistCompiler或JdkCompiler的实现:

  • AbstractCompiler
public abstract class AbstractCompiler implements Compiler {

    // 定义package正则匹配
    private static final Pattern PACKAGE_PATTERN = Pattern.compile("package\\s+([$_a-zA-Z][$_a-zA-Z0-9\\.]*);");
    // 定义class正则匹配
    private static final Pattern CLASS_PATTERN = Pattern.compile("class\\s+([$_a-zA-Z][$_a-zA-Z0-9]*)\\s+");
    /*
    *   编译code生成Class
     */
    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 {
            // 尝试使用反射直接加载该Class,如果不存在则抛出异常,进入catch块中
            return Class.forName(className, true, ClassHelper.getCallerClassLoader(getClass()));
        } catch (ClassNotFoundException e) {
            if (!code.endsWith("}")) {
                throw new IllegalStateException("The java code not endsWith \"}\", code: \n" + code + "\n");
            }
            try {
                // 模板方法模式
                // 使用子类实现的doCompile方法编译生成Class
                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: \n" + code + "\n, stack: " + ClassUtils.toString(t));
            }
        }
    }

    /*
    *   由子类提供具体实现
     */
    protected abstract Class<?> doCompile(String name, String source) throws Throwable;

}
3.2.3、JavassistCompiler
public class JavassistCompiler extends AbstractCompiler {

    // import匹配
    private static final Pattern IMPORT_PATTERN = Pattern.compile("import\\s+([\\w\\.\\*]+);\n");
    // extends匹配
    private static final Pattern EXTENDS_PATTERN = Pattern.compile("\\s+extends\\s+([\\w\\.]+)[^\\{]*\\{\n");
    // implements匹配
    private static final Pattern IMPLEMENTS_PATTERN = Pattern.compile("\\s+implements\\s+([\\w\\.]+)\\s*\\{\n");
    // 方法匹配
    private static final Pattern METHODS_PATTERN = Pattern.compile("\n(private|public|protected)\\s+");
    // 变量匹配
    private static final Pattern FIELD_PATTERN = Pattern.compile("[^\n]+=[^\n]+;");

    /*
    *   name:类全限定名
    *   source:Java代码
     */
    @Override
    public Class<?> doCompile(String name, String source) throws Throwable {
        int i = name.lastIndexOf('.');
        // 获取到类名称
        String className = i < 0 ? name : name.substring(i + 1);
        // 创建Javassist ClassPool,开始构建Class
        ClassPool pool = new ClassPool(true);
        // 设置类搜索路径
        pool.appendClassPath(new LoaderClassPath(ClassHelper.getCallerClassLoader(getClass())));
        // 匹配 import
        Matcher matcher = IMPORT_PATTERN.matcher(source);
        // 引用的包名
        List<String> importPackages = new ArrayList<String>();
        // 引用的类名
        Map<String, String> fullNames = new HashMap<String, String>();
        while (matcher.find()) {
            String pkg = matcher.group(1);
            // 引用整个包下的类和接口
            if (pkg.endsWith(".*")) {
                String pkgName = pkg.substring(0, pkg.length() - 2);
                pool.importPackage(pkgName);
                importPackages.add(pkgName);
            } else {
                // 引用指定类和接口
                int pi = pkg.lastIndexOf('.');
                if (pi > 0) {
                    String pkgName = pkg.substring(0, pi);
                    pool.importPackage(pkgName);
                    importPackages.add(pkgName);
                    fullNames.put(pkg.substring(pi + 1), pkg);
                }
            }
        }
        // 获取到所有需要import的类
        String[] packages = importPackages.toArray(new String[0]);
        matcher = EXTENDS_PATTERN.matcher(source);
        CtClass cls;
        if (matcher.find()) {
            String extend = matcher.group(1).trim();
            String extendClass;
            if (extend.contains(".")) {
                extendClass = extend;
            } else if (fullNames.containsKey(extend)) {
                extendClass = fullNames.get(extend);
            } else {
                extendClass = ClassUtils.forName(packages, extend).getName();
            }
            // 为cls添加extends的类
            cls = pool.makeClass(name, pool.get(extendClass));
        } else {
            cls = pool.makeClass(name);
        }
        matcher = IMPLEMENTS_PATTERN.matcher(source);
        if (matcher.find()) {
            String[] ifaces = matcher.group(1).trim().split("\\,");
            for (String iface : ifaces) {
                iface = iface.trim();
                String ifaceClass;
                if (iface.contains(".")) {
                    ifaceClass = iface;
                } else if (fullNames.containsKey(iface)) {
                    ifaceClass = fullNames.get(iface);
                } else {
                    ifaceClass = ClassUtils.forName(packages, iface).getName();
                }
                // 为cls添加implement的接口
                cls.addInterface(pool.get(ifaceClass));
            }
        }
        // 开始匹配类的主体构造方法、public方法和private方法
        String body = source.substring(source.indexOf("{") + 1, source.length() - 1);
        String[] methods = METHODS_PATTERN.split(body);
        // 匹配完方法,并为cls添加上去
        for (String method : methods) {
            method = method.trim();
            if (method.length() > 0) {
                // 构造方法
                if (method.startsWith(className)) {
                    cls.addConstructor(CtNewConstructor.make("public " + method, cls));
                } else if (FIELD_PATTERN.matcher(method).matches()) {
                    // 私有方法
                    cls.addField(CtField.make("private " + method, cls));
                } else {
                    // 公有方法
                    cls.addMethod(CtNewMethod.make("public " + method, cls));
                }
            }
        }
        // 通过cls创建Class
        return cls.toClass(ClassHelper.getCallerClassLoader(getClass()), JavassistCompiler.class.getProtectionDomain());
    }

}
精尽 Dubbo 源码分析 —— 动态编译(一)之 Javassist 1.概述 在 Java 语言中,大多数情况下,我们已经编写好 Java 类,并编译成 Class 文件进行运行。但是在一些场景下,例如动态代理,需要运用到动态编译的技术 例如,SPI中的 createAdaptiveExtensionClassCode方法中,我们可以看到如下代码: /** * 自动生成自适应拓展的代码实现,并编译后返回该类。 * * @ret... 阅读详情

相关推荐

NoUnityCN:绕过地域限制,从Unity官方CDN直链下载全版本编辑器

在软件开发和游戏制作领域,内容分发网络(CDN)是保障全球用户高速、稳定获取大型文件的核心基础设施。其原理是通过将资源缓存至遍布各地的边缘节点,使用户能从地理距离最近的服务器获取数据,从而显著提升下载速度并降低源站压力。这一技术对于需要频繁下载大型开发工具(如游戏引擎)的团队而言,价值在于能确保开发环境部署的一致性与效率,是构建自动化CI/CD流水线和团队协作的基础。然而,当开发者因网络策略或地域限制无法直接访问官方CDN时,获取安装文件便成为阻碍工作流的痛点。NoUnityCN项目正是针对此场景的工程实践

weixin_33473110的博客 318

dubbo的动态编译javassist

一. javassist简介 Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京技术学院的数学和计算机科学系的 Shigeru Chiba 所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态AOP框架。 Javassist(JAVA编程ASSISTant)使Java字节码操作变得简单。 它是一个用Java编辑字节码的类库; 它使Java程序能够在运行时定义新类,并在JVM加载时修改类文件。 与其他类似的字节码编辑器不

景川的博客 1470

ISCC练习题MISC

解题技巧:看最后括号应该是IceCTF,先用了一键解码啥也没有啊,不对不对!好像是字符频率统计,转换网站:http://quipqiup.com/有人给你发了一串信息,你能解开吗?

m0_62737381的博客 1120

javassist 入门以及dubbo中的使用案例

学习javassite 不得不提的javaagent 技术,字节码插桩 如果不太了解的可以参考Javaagent入门这一篇文章自己有一个简单的大致了解Javassist是一个开源的分析、编辑和创建Java字节码的类库。其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成Javassist 应用场景:监控、动态代理dubbo、myBatis、Spring 都有不同程度的应用。

1570

TS808效果器制作教程

TS808效果器制作教程 可以在立创商城购买到大部分的电阻电容和IC,音频接口,踩钉,电位器和电源接口可以去某宝看看都买得到的。链接https//pan.baidu.com/s/1QId1eIE3fJ2u5NLBSISvGA。安装过程过于繁琐,把所有元器件按照图纸焊接完成就可以调试了,祝你们成功!这是TS808经典效果器制作过程的记录。IC是JRC4558。...

qq_18948149的博客 3429

让Qt程序适配高分辨率屏幕,解决软件界面错乱异常

前期使用Qt开发一个登录模块一直使用很好。最近在一台新电脑上使用时发现排版混乱。这个问题很普遍,主要原因是旧软件对高清显示器的适配不当造成的。新电脑使用的是4K屏,win10系统自动进行了175%的缩放。

cihron的博客 1万+

Dubbo的Javassist代理

Javassist 生成动态代理可以使用两种方式,一种使用代理工厂创建,和普通的JDK动态代理和 CGLIB类似,另一种则可以使用 动态代码创建。 Dubbo无论是生产端的暴露服务创建的invoker代理还是消费端创建的代理调用,都会需要经过代理。而Dubbo中默认采用javassit代理,动态的在内存当中生成所代理类的字节码,来完成代理的功能。 可以看到,javassit的代理工厂类只实...

吒哇 1135

给大一新生的蓝桥杯EDA备赛规划:从电路分析到立创EDA,如何用一年时间高效备赛?

本文为大一新生提供了一份系统的蓝桥杯EDA备赛规划,从电路分析基础到立创EDA实战操作,分阶段指导如何高效备赛。内容涵盖理论学习、软件操作、PCB设计专项提升及冲刺优化策略,帮助学生在一年内全面提升电子设计能力,为竞赛做好充分准备。

weixin_31476015的博客 290

Dubbo源码解析-动态编译javaAssist的使用

前言: 在Dubbo中,大量使用动态代理相关技术。动态代理主要是基于JDK的动态代理和Javassist的动态代理。 有关于JDK动态代理的使用及源码解析可以参考上文。 本文着重来介绍下Javassist的使用,及其动态代理的实现。 1.Javassist简介 Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss 应用服务器项...

恐龙弟旺仔的博客 1320

前端使用二开Thingsboard一、二、三事(三)-规则链

以项目实战为基础,逐步介绍前端在thingsboard系统二次开发中的一些注意事项以及一些thingsboard一些页面功能讲解,为前端人员开发使用thingsboard提供一种可靠思路,打造一个完美的物联网系统。

weixin_43163457的博客 863

B站自动答题协议分析

使用Python写了一个自动答题机器人!基于接口协议实现且包含点选验证码识别

吴秋霖的博客 2656

Dubbo源码分析系列-Dubbo的动态编译原理

导语   Java程序时运行在JVM中的Class文件,在一般的情况下都是把左右的Java文件编写完成之后,统一进行编译操作,做完编译操作之后,统一由JVM进行加载。而所谓的动态编译则是在JVM进程运行的过程中把源文件编译为字节码文件,然后使用字节码文件创建对象实例。在Dubbo中提供了一个SPI接口,通过这个接口来动态的生成对应的适配器类。下面就来看看在Dubbo中是如何生成这个适配器类  ...

初学者 2809

学Simulink——基于Simulink的固态变压器(SST)多级协同控制​

本文介绍了基于Simulink的固态变压器(SST)多级协同控制系统设计与仿真方法。SST作为智能电网关键设备,包含AC-DC整流、DC-DC隔离和DC-AC逆变三级变换器。针对级间耦合问题,提出了能量-功率协同控制策略,通过纵向解耦和横向联动实现稳定运行。详细演示了在Simulink中搭建三级主电路、设计协同控制器(含电网定向控制、功率前馈和虚拟惯性控制)的全过程,并通过负载突变测试验证了系统动态性能(直流母线电压波动<2%)。最后给出了工程部署建议,包括数字控制延时补偿、启动序列设计和代码自动生成

xiaoheshang_123的博客 206

深度解析dubbo动态编译技术

深度解析dubbo动态编译技术

猿上生活 1542

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Dubbo 2.7 源码解析 - Dubbo的AOP源码解析、Dubbo的动态编译Compile源码解析

Apache Dubbo 2.7 是一个高性能、轻量级的开源微服务框架,它提供了服务自动发现、负载均衡、服务治理等功能。在理解Dubbo的AOP(面向切面编程)和动态编译(Compile)机制之前,我们先简要回顾一下这两个概念在Dubbo中的应用场景,然后深入到源码层面进行解析。

qq_33240556的博客 648

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

深度解析dubbo源码系列

以下文章均基于dubbo v2.6.1 持续更新中… dubbo spi 扩展技术,框架基石 《深度解析dubbo扩展技术dubbo spi(注解)》 《深度解析dubbo扩展技术dubbo spi(实现二)》 《深度解析dubbo扩展技术dubbo spi(自适应实现)》 《深度解析dubbo扩展技术dubbo spi(自动激活实现)》 服务暴露 《深度解析dubbo服务本地暴露(injvm)》 《深度解析dubbo服务远程暴露(一)》 《深度解析dubbo服务远程暴露(二)》 《深度解析dubbo

猿上生活 1万+

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Dubbo源码分析 - 动态编译

Dubbo源码分析 - 动态编译 概述 在Dubbo自适应扩展中,我们已经得到了自适应扩展类的字符串,需要通过编译才能得到真正的Class,本篇文章就来介绍将类的字符串编译成类的过程。 动态编译 dubbo 的动态编译的整体结构如上图所示。dubbo中的Compiler基于dubbo spi机制进行加载,目前支持jdk和javassist两种实现: <dubbo:application compiler="jdk" /> <dubbo:application compiler="java

gentryhuang的博客 666

dubbo源码解析(4) dubbo的动态编译

前面几节我们分析了dubbo的spi、ioc和aop,这一篇我们探究dubbo的最后一个内核,动态编译 在分析动态编译前,先介绍下javassitst Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作...

m0_37139189的博客 291

Dubbo(十)内核源码解析(Dubbo的AOP源码解析、Dubbo的动态编译Compile源码解析)

1. Dubbo 的 AOP 源码解析 Dubbo 的 AOP 是对 SPI 扩展类进行增强的方式,而 Wrapper 机制就是对 SPI 扩展类的增强。不同 SPI 的不同 Wrapper,其增强的功能不同。为了方便大家的理解,我们就以前面在学习“Wrapper 机制”时写的代码 15-wrapper 为例进行源码解析,来查看扩展类是如何被包装起来的。 1.1 找到 AOP 源码 META-INF/dubbo/internal/com.abc.spi.Order alipay=com.abc.spi.ex

语雀同名:犬豪 yuque.com/qhao 652

dubbo2.7.3源码解析

2.7.3版本 ExtensionLoader#createAdaptiveExtensionClass方法 String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate(); 会生成Adaptive自适应代码 Dubbo标签优先级排序示意图 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8YiFozRq-1591684569860)(dubbo.assets/158945707

Yxf的博客 920

dubbo源码分析之javassist动态编译-3

我们运行的Java代码,一般都是编译之后的字节码。Dubbo为了实现基于SPI思想的扩展特性,可以灵活的添加额外的功能。对于SPI接口需要能够动态生成,这样就需要在运行的时候去编译加载这个设配类的代码。下面我们就是来了解下Dubbo的动态编译。 我们首先来看一下Compile的类图。 Compile接口定义: @SPI("javassist") public interface Compil...

Jack博客 667

3.dubbo源码分析 之 动态编译

原文地址:http://www.carlzone.cn/dubbo/3-dubbo-compile/我们运行的Java代码,一般都是编译之后的字节码。Dubbo为了实现基于SPI思想的扩展特性,可以灵活的添加额外的功能。对于SPI接口需要能够动态生成,这样就需要在运行的时候去编译加载这个设配类的代码。下面我们就是来了解下Dubbo的动态编译。我们首先来看一下Compile的类图。Compile接口...

Yang_yangyang的博客 393

Dubbo的适配器原理、动态编译原理

适配器原理、动态编译原理适配器原理动态编译原理 适配器原理 Dubbo 为 每个功能点 提供了 一个SPI扩展接口,Dubbo框架 在使用 扩展点功能的时候 是对 接口进行依赖的,而一个扩展接口 对应了 一系列的扩展实现类 那么如何选择 使用哪一个 扩展接口的实现类呢 其实这是 使用 适配器模式 来做的 首先看看什么是适配器模式,比如Dubbo提供的扩展接口Protocol,其定义如下 @SPI("dubbo") public interface Protocol { // 自适应 @Adaptive

星光之子的博客 422

Dubbo源码解析实战 - 服务暴露原理

欢迎关注全是干货的技术公众号 dubbo面试中比较喜欢问的两个点:服务发布和服务引用. 人性的拷问 服务发布过程中做了哪些事 dubbo都有哪些协议,他们之间有什么特点,缺省值是什么 什么是本地暴露和远程暴露,他们的区别 直入主题 从启动日志说起 这里不同颜色的框将关键的地方画了出来,一共有6种颜色, 从上到下 暴露本地服务 暴露远程服务 启动netty 连接zookeeper 到zoo...

JavaEdge全是干货的技术号 4416

Dubbo源码之动态编译

Dubbo里的代理类 JavassistProxyFactory:利用字节码技术来创建对象 public <T> T getProxy(Invoker<T> invoker,Class<?>[] interfaces) { return (T) Proxy.getProxy(interfaces).newInstance(newInvoker...

数据与算法架构提升之路专栏 731
上一篇: Dubbo源码(1)-SPI机制源码解析
下一篇: Dubbo源码(3)-基础抽象注册中心源码解析
BoringRong
BoringRong 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 2万+粉丝 386原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BoringRong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值