ByteBuddy学习笔记

ByteBuddy

1.ByteBuddy的用途

ByteBuddy通过修改字节码来新增、修改、删除Java类的现有功能,主要用于分离功能代码和非功能代码,比如
ByteBuddy学习笔记_第1张图片
比如非功能代码如下:

public double calculatePrice(){
   double discount = getDiscount();
   double price = this.price + this.deliveryCharge - discount;
   return price;
}

添加比如打印日志等非功能代码,形成如下的内容:

public double calculatePrice(){
   long startTime = System.currentMilliseconds();
   logger.info("CalculatePrice start");
   double discount = getDiscount();
   double price = this.price + this.deliveryCharge - discount;
   logger.info("Method end");
   logger.info("CalculatePrice execution time: " + (System.currentMillioseconds() - startTime));
   return price;
}

2.ByteBuddy的初始化代码学习

首先在maven的dependencies标签之中配置上需要用到的库

        
            net.bytebuddy
            byte-buddy
            1.12.20
        

        
            net.bytebuddy
            byte-buddy-agent
            1.12.20
        

        
            net.bytebuddy
            byte-buddy-maven-plugin
            1.12.20
        
        
            org.junit.jupiter
            junit-jupiter
            RELEASE
            compile
        

然后学习示例的代码

    public void test() throws InstantiationException, IllegalAccessException {
        DynamicType.Unloaded unloadedType = new ByteBuddy()
                //创建ByteBuddy类型的一个实例
                .subclass(Object.class)
                //动态创建的类是继承Object的
                .method(ElementMatchers.isToString())
                //method为筛选器,筛选Object中的toString方法
                .intercept(FixedValue.value("Hello World ByteBuddy!"))
                //提供了toString()的实现,返回固定值"Hello World ByteBuddy!"
                //按照下面的最后定义函数优先,这里的类
                .make();
                //触发生成一个新的类
        Class<?> dynamicType = unloadedType.load(getClass()
                .getClassLoader())
                .getLoaded();
                //把unloadedType实例加载到JVM之中,此时dynamicType相当于一个类
        Assertions.assertEquals(dynamicType.newInstance().toString(),"Hello World ByteBuddy!");
        //调用dynamicType.toString()方法不会生效,因为此时调用的是ByteBuddy.class的toString()方法
    }

3.ByteBuddy调用的优先级部分

    public void test() throws InstantiationException, IllegalAccessException {
        String r = new ByteBuddy()
                .subclass(Foo.class)
                .method(named("sayHelloFoo")
                                .and(isDeclaredBy(Foo.class))
                                .and(returns(String.class)))
                //符合三个条件的方法
                .intercept(MethodDelegation.to(Bar.class))
                .make()
                .load(getClass().getClassLoader())
                .getLoaded()
                .newInstance()
                .sayHelloFoo();
        assertEquals(r,Bar.sayHelloBar());
    }

intercept提供了类的实现,因为这里的intercept初始化的是Bar.class,而Bar和Foo的类中都有sayHelloBar这个方法,因此这里最终实现的是Bar的sayHelloBar方法

你可能感兴趣的:(java学习笔记,学习,笔记)