zoukankan      html  css  js  c++  java
  • ByteBuddy实现动态代理

    介绍

    ByteBuddy也是一个代码生成和操作的类库,可以在运行时动态创建和修改class,底层也是ASM库,相比于cglib,javassist,Bytebuddy在性能上具有优势,Hibernate的懒加载和mockito测试框架都使用到了Bytebuddy。官网

    实现动态代理

    maven依赖

    <dependency>
      <groupId>net.bytebuddy</groupId>
      <artifactId>byte-buddy</artifactId>
      <version>1.10.13</version>
    </dependency>
    

    代理接口

    /**
     * 可以唱歌的
     */
    public interface Singable {
      /**
       * 唱歌
       */
      void sing();
    }
    

    被代理类

    /**
     * 歌手
     */
    public class Singer implements Singable {
      @Override
      public void sing() {
        System.out.println("I am singing...");
      }
    }
    

    通过代理接口实现

    public class Client {
    
      public static void main(String[] args) throws Exception {
        Singable proxy = createByteBuddyDynamicProxy();
        proxy.sing();
        System.out.println(proxy.toString());
      }
    
      private static Singable createByteBuddyDynamicProxy() throws Exception {
        return (Singable) new ByteBuddy().subclass(Object.class)
            .implement(Singable.class)
            .method(ElementMatchers.named("sing"))
            .intercept(InvocationHandlerAdapter.of(new SingerInvocationHandler(new Singer())))
            .make()
            .load(Client.class.getClassLoader())
            .getLoaded()
            .getDeclaredConstructor()
            .newInstance();
      }
    
      public static class SingerInvocationHandler implements InvocationHandler {
    
        private Object delegate;
    
        public SingerInvocationHandler(Object delegate) {
          this.delegate = delegate;
        }
    
        /**
         * 动态代理调用方法
         *
         * @param proxy 生成的代理对象
         * @param method 代理的方法
         * @param args 方法参数
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          System.out.println("bytebuddy proxy before sing ");
          Object ret = method.invoke(delegate, args);
          System.out.println("bytebuddy proxy after sing ");
          return ret;
        }
    
      }
    }
    

    继承Object,实现Singable接口,通过适配JDK的InvocationHandler实现方法的拦截。

    public class Client {
    
      public static void main(String[] args) throws Exception {
        Singable proxy = createByteBuddyDynamicProxy();
        proxy.sing();
        System.out.println(proxy.toString());
      }
    
      private static Singable createByteBuddyDynamicProxy() throws Exception {
        return (Singable) new ByteBuddy().subclass(Object.class)
            .implement(Singable.class)
            .method(ElementMatchers.named("sing"))
            .intercept(MethodDelegation.to(new SingerAgentInterceptor(new Singer())))
            .make()
            .load(Client.class.getClassLoader())
            .getLoaded()
            .getDeclaredConstructor()
            .newInstance();
      }
    
      public static class SingerAgentInterceptor {
    
        private Object delegate;
    
        public SingerAgentInterceptor(Object delegate) {
          this.delegate = delegate;
        }
    
        /**
         * @param proxy 代理对象
         * @param method 代理方法
         * @param args 方法参数
         */
        public Object interceptor(@This Object proxy, @Origin Method method,
            @AllArguments Object[] args) throws Exception {
          System.out.println("bytebuddy delegate proxy before sing ");
          Object ret = method.invoke(delegate, args);
          System.out.println("bytebuddy delegate proxy after sing ");
          return ret;
        }
      }
    
    }
    

    我们也可以通过方法委托(MethodDelegation)的方式实现拦截器,
    @This 表示生成的代理对象
    @Origin 表示被代理的方法
    @AllArguments 表示方法参数

    通过代理类实现

    public class Client {
    
      public static void main(String[] args) throws Exception {
        Singable proxy = createByteBuddyDynamicProxy();
        proxy.sing();
        System.out.println(proxy.toString());
      }
    
      private static Singable createByteBuddyDynamicProxy() throws Exception {
        return (Singable) new ByteBuddy().subclass(Singer.class)
            .implement(Singable.class)
            .method(ElementMatchers.named("sing"))
            .intercept(MethodDelegation.to(new SingerAgentInterceptor()))
            .make()
            .load(Client.class.getClassLoader())
            .getLoaded()
            .getDeclaredConstructor()
            .newInstance();
      }
    
      public static class SingerAgentInterceptor {
    
        public Object interceptor(@This Object proxy, @Origin Method method,
            @SuperMethod Method superMethod,
            @AllArguments Object[] args) throws Exception {
          System.out.println("bytebuddy delegate proxy2 before sing ");
          Object ret = superMethod.invoke(proxy, args);
          System.out.println("bytebuddy delegate proxy2 after sing ");
          return ret;
        }
      }
    
    }
    

    继承Singer类,@SuperMethod 表示父类的方法。

  • 相关阅读:
    CV 第十一课 Segmentation Localization Detection 下
    面经
    overfitting问题
    CV 第十一课 Segmentation Localization Detection 上
    CV 第十一课 Classification + Localization 中
    SVM的特点
    UNSW CV第二课 上 Image Prepocessing
    UNSW CV Assignment1
    UNSW CV 第一课 下 投影 RGB HSV
    HDU 4350
  • 原文地址:https://www.cnblogs.com/strongmore/p/13562640.html
Copyright © 2011-2022 走看看