dubbo源码分析之动态编译

我们运行的Java代码,都是编译之后的字节码,dubbo为了实现了基于spi思想的扩展特性,特别是能够灵活添加额外功能。dubbo作为一个高扩展性的框架,使的用户能够添加自己的需求,根据配置动态生成自己的设配类代码,这样就需要在运行的时候去编译加载这个设配类的代码。下面我们就是来了解下Dubbo的动态编译。

这里写图片描述

编译接口定义

@SPI("javassist")
public interface Compiler {

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

}

dubbo默认选用javassist编译源代码,接口方法compile第一入参是code,代表Java源代码,第二个入参classLoader,代表加载编译后的字节码的类加载器,根据当前线程或调用方classLoader加载的

@Adaptive注解在标注@SPI接口的实现类上,扩展类就是这个类。

例如这里的Compiler的SPI扩展就是AdaptiveCompiler这个类。AdaptiveCompiler是Compiler的设配类, 它有类注解@Adaptive表示这个Compiler的设配类不是动态编译生成的。AdaptiveCompiler作用就是策略的选择,根据条件选择何种编译策略来编译动态生成的源代码。默认为javassist.

//@Adaptive表示这个Compiler的设配类不是动态编译生成的
@Adaptive
public class AdaptiveCompiler implements Compiler {

    private static volatile String DEFAULT_COMPILER;

    public static void setDefaultCompiler(String compiler) {
        DEFAULT_COMPILER = compiler;
    }

    @Override
    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) {
            compiler = loader.getExtension(name);
        } else {
            compiler = loader.getDefaultExtension();
        }
        return compiler.compile(code, classLoader);
    }

}

AbstractCompiler是一个抽象类,它通过正则表达式获取到对象的包名以及Class名称。这样就可以获取对象的全类名(包名+Class名称)。通过反射Class.forName()来判断当前ClassLoader是否有这个类,如果有就返回,如果没有就通过JdkCompiler或者JavassistCompiler通过传入的code编译这个类。

public abstract class AbstractCompiler implements Compiler {
    //通过正则表达式获取到对象的包名以及Class名称。
    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+");

    @Override
    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);
        }
       // 获取对象的全类名(包名+Class名称)
        String className = pkg != null && pkg.length() > 0 ? pkg + "." + cls : cls;
        try {
           //通过反射Class.forName()来判断当前ClassLoader是否有这个类,如果有就返回
            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 {
            //如果没有就通过JdkCompiler或者JavassistCompiler通过传入的code编译这个类。
                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;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值