首页 > 解决方案 > 使用 Bytebuddy 动态创建类和方法

问题描述

我是 bytebuddy 的新手,我想动态创建一个类并使用 byte buddy 执行如下代码。

public class Formulas{
    public double formula1234(FormulaAPI apiReference) {
                                if(apiReference.getId() > 0){
                                      return apiReference.evaluate("A") * 2;
                                }else if(apiReference.getId() == 1){
                                       return apiReference.evaluate("B");
                                }else{
                                     return apiReference.getSum(x1, x2);
                                }
                                return null;
 }
}

FormulaAPI已经定义了类,它有方法 ->evaluate(..)getSum(..)在其中定义。

我想用byte buddy动态创建一个叫Formulas的类,动态构造方法formula1234(..)和方法里面的代码。

甚至可以使用字节伙伴构造 if else 语句吗?

请您举例说明如何使用 byte buddy 动态生成此代码。任何帮助表示赞赏。

标签: javadynamicbyte-buddyclassloading

解决方案


java中的代码生成不是那么容易,所以不经常使用。特别是与具有类似功能的语言相比eval()

您在 java 中使用的一种常见方法是使用策略列表/映射。在您的情况下, strategy(*) 将包含两种方法。检查是否应应用策略以及实际执行的条件。

这是一个自包含的示例:

public static void main(String[] args) {

    Formulas formulas = new Formulas();

    formulas.addFormula(api -> api.getApi() == 0, api -> api.getVal1() + api.getVal2());
    formulas.addFormula(api -> api.getApi() == 1, api -> api.getVal1() + 25d);
    formulas.addFormula(api -> api.getApi() == 2, api -> api.getVal2() - api.getVal1());

    System.out.println(formulas.formula123(new Api(0, 1, 2)));
    System.out.println(formulas.formula123(new Api(1, 2, -5)));
    System.out.println(formulas.formula123(new Api(2, 5, -5)));

}

public static class Api {
    private final int api;

    private final double val1;
    private final double val2;

    public Api(int api, double val1, double val2) {
        this.api = api;
        this.val1 = val1;
        this.val2 = val2;
    }

    public int getApi() {
        return api;
    }

    public double getVal1() {
        return val1;
    }

    public double getVal2() {
        return val2;
    }

}

public static class Formula {

    private final Predicate<Api> condition;
    private final Function<Api, Double> execute;

    public Formula(Predicate<Api> condition, Function<Api, Double> execute) {
        this.condition = condition;
        this.execute = execute;
    }

    public Predicate<Api> getCondition() {
        return condition;
    }

    public Function<Api, Double> getExecute() {
        return execute;
    }

}

public static class Formulas {
    private final List<Formula> formulas = new ArrayList<>();

    public void addFormula(Predicate<Api> condition, Function<Api, Double> execute) {
        formulas.add(new Formula(condition, execute));
    }

    public Double formula123(Api api) {
        for (Formula formula : formulas) {
            if (formula.getCondition().test(api)) {
                return formula.getExecute().apply(api);
            }
        }
        return null;
    }
}

(*) 不知道这是否仍然算作两种方法的策略。


推荐阅读