byte buddy学习笔记

参考网址https://notes.diguage.com/byte-buddy-tutorial/
1、Maven依赖:

net.bytebuddy
byte-buddy
1.7.9


net.bytebuddy
byte-buddy-agent
1.7.9

2、Byte Buddy 的默认配置提供了 NamingStrategy,它基于动态类型的超类名称来随机生成类名。

    public static void main(String[] args) {
        DynamicType.Unloaded<?> dynamicType = new ByteBuddy()
                .with(new NamingStrategy.AbstractBase() {
                    @Override
                    protected String name(TypeDescription typeDescription) {
                        return "i.love.ByteBuddy." + typeDescription.getSimpleName();
                    }

                })
                .subclass(Object.class)
                .make();
        DynamicType.Unloaded<?> dynamicType1 = new ByteBuddy()
                .with(new NamingStrategy.AbstractBase() {
                    @Override
                    protected String name(TypeDescription typeDescription) {
                        return "i.love.ByteBuddy." + typeDescription.getSimpleName();
                    }

                })
                .subclass(Object.class)
                .make();
        System.out.println(dynamicType.getTypeDescription().getCanonicalName());
        System.out.println(dynamicType1.getTypeDescription().getCanonicalName());

        ByteBuddy byteBuddy = new ByteBuddy();
        byteBuddy.with(new NamingStrategy.SuffixingRandom("suffix"));
        DynamicType.Unloaded<?> dynamicType3 = byteBuddy.subclass(Object.class).make();
        System.out.println(dynamicType3.getTypeDescription().getCanonicalName());

        ByteBuddy byteBuddy1 = new ByteBuddy();
        DynamicType.Unloaded<?> dynamicType4 = byteBuddy1.with(new NamingStrategy.SuffixingRandom("suffix")).
                subclass(Object.class).make();
        System.out.println(dynamicType4.getTypeDescription().getCanonicalName());

        ByteBuddy byteBuddy3 = new ByteBuddy();
        ByteBuddy suffix = byteBuddy3.with(new NamingStrategy.SuffixingRandom("suffix"));
        DynamicType.Unloaded<?> dynamicType5 = suffix.
                subclass(Object.class).make();
        System.out.println(dynamicType5.getTypeDescription().getCanonicalName());
    }

输出:
这里写图片描述
Byte Buddy 中,几乎所有的类都被构建成不可变的;调用 with 方法返回一个新的自定义的 ByteBuddy 实例。

3、类型重定义(type redefinition)
当重定义一个类时,Byte Buddy 可以对一个已有的类添加属性和方法,或者删除已经存在的方法实现。如果使用其他的方法实现替换已经存在的方法实现,则原来存在的方法实现就会消失。
这里写图片描述
4、类型重定基底(type rebasing)
当重定基底一个类时,Byte Buddy 保存基底类所有方法的实现。当 Byte Buddy 如执行类型重定义时,它将所有这些方法实现复制到具有兼容签名的重新命名的私有方法中,而不是抛弃重写的方法。
这里写图片描述
new ByteBuddy().subclass(Foo.class) 创建子类
new ByteBuddy().redefine(Foo.class) 重定义
new ByteBuddy().rebase(Foo.class) 重定基底

5、加载类
DynamicType.Unloaded 的实例表示,这些类型不会加载到 Java 虚拟机中。DynamicType.Unloaded 类允许提取表示动态类型的字节数组。为方便起见,该类型还提供了一个 saveIn(File) 方法,可以将类存储在给定的文件夹中。此外,它允许您使用 inject(File) 方法将类注入到现有的 Jar 文件中。

创建 DynamicType.Unloaded 之后,可以使用 ClassLoadingStrategy 加载此类型。Byte Buddy提供了几种类加载策略,这些策略定义在 ClassLoadingStrategy.Default 中,其中 WRAPPER 策略创建一个新的包装 ClassLoader;CHILD_FIRST 策略创建一个类似于第一个子类优先的类加载器;INJECTION 策略使用反射注入动态类型。

public class Main1 {
    public static void main(String[] args) {
        Main1 main1 = new Main1();
        Class test = main1.test();
        System.out.println("!"+test.toString());
    }

    private Class test(){
        Class<?> type = new ByteBuddy()
                .subclass(Object.class)
                .name("loadedClass")
                .make()
                .load(this.getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
                .getLoaded();
        return type;
    }
}

输出:

!class loadedClass

在上面的例子中,我们创建并加载了一个类。我们使用 WRAPPER 策略来加载适合大多数情况的类,就像我们之前提到的那样。最后,getLoaded 方法返回一个 Java Class 的实例,它就表示现在加载的动态类。

6、重新加载类

public class Main2 {
    public static void main(String[] args) {
        ByteBuddyAgent.install();
        Foo foo = new Foo();
        new ByteBuddy()
                .redefine(Bar.class)
                .name(Foo.class.getName())
                .make()
                .load(Foo.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
        System.out.println(foo.m());
    }
}

class Foo {
    String m() { return "foo"; }
}

class Bar {
    String m() { return "bar"; }
}

输出:

bar
发布了45 篇原创文章 · 获赞 18 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_26761587/article/details/78798194
今日推荐