简体   繁体   中英

Decorate a method with ByteBuddy

How can I define a method and then decorate it (multiple times) with ByteBuddy ? This is my example

Builder<Object> builder = new ByteBuddy().subclass(Object.class).name("Dynamic");
    builder = builder.defineMethod("method", void.class, Visibility.PUBLIC)
    .intercept(MethodDelegation.to(new Object(){

        @RuntimeType
        public void intercept(@This Object o) {
            System.out.println("Executing code...");
        }

    }));

    builder = builder.method(ElementMatchers.named("method")).
    intercept(MethodDelegation.to(new Object(){

        @RuntimeType
        public void intercept(@This Object o) {
            System.out.println("Executing other code...");
        }

    }));

    try {
        Class cls = builder.make()
                .load(StructClassBuilder.class.getClassLoader())
                .getLoaded();

        Object obj = cls.newInstance();
        cls.getDeclaredMethod("method").invoke(obj, args);
    } catch (Exception e1) {
        e1.printStackTrace();
    }

The output is

Executing other code...

I would like that the output is

Executing code...

Executing other code...

Thanks

One option is to chain Your interceptors using MethodDelegation.to(...).addThen(...) methods.

public class ByteBuddyTest {

  public static void main(String[] args) throws Exception {
    DynamicType.Builder<Object> builder = new ByteBuddy().subclass(Object.class).name("Dynamic");
    builder = builder
        .defineMethod("method", void.class, Visibility.PUBLIC)
        .intercept(MethodDelegation.to(Interceptor1.class).andThen(MethodDelegation.to(Interceptor2.class)));

    try {
        Class<?> clazz = builder.make().include().load(ByteBuddyTest.class.getClassLoader()).getLoaded();

        Object obj = clazz.newInstance();
        clazz.getDeclaredMethod("method").invoke(obj, args);
    } catch (Exception e1) {
        e1.printStackTrace();
    }
  }

  public static class Interceptor1 {

      public static void intercept() {
          System.out.println("Executing code...");
      }
  }

  public static class Interceptor2 {

      public static void intercept() {
          System.out.println("Executing other code...");
      }
  }
}

I'll use decorator pattern to decorate the Interceptor, now it works as expected. I share my solution:

private static interface Interceptor{
    public void intercept(@This Object o);
}

private abstract static class InterceptorDecorator implements Interceptor{

    protected Interceptor interceptor;

    public InterceptorDecorator(Interceptor interceptor){
        this.interceptor = interceptor;
    }

    public void intercept(@This Object o) {
        if(interceptor!=null){
            interceptor.intercept(o);       
        }
    }

}

private static class Interceptor1 extends InterceptorDecorator{

    public Interceptor1(Interceptor interceptor) {
        super(interceptor);
    }

    public void intercept(@This Object o) {
        super.intercept(o);
        System.out.println("Executing code...");            
    }

}

private static class Interceptor2 extends InterceptorDecorator{

    public Interceptor2(Interceptor interceptor) {
        super(interceptor);
    }

    public void intercept(@This Object o) {
        super.intercept(o);
        System.out.println("Executing other code...");          
    }

}

public static void main(String[] args) {

    Interceptor interceptor = new Interceptor1(null);
    interceptor = new Interceptor2(interceptor);

    Builder<Object> builder = new ByteBuddy().subclass(Object.class).name("Dynamic");
    builder = builder.defineMethod("method", void.class, Visibility.PUBLIC)
    .intercept(MethodDelegation.to(interceptor));

    try {
        Class cls = builder.make()
                .load(StructClassBuilder.class.getClassLoader())
                .getLoaded();

        Object obj = cls.newInstance();
        cls.getDeclaredMethod("method").invoke(obj, args);
    } catch (Exception e1) {
        e1.printStackTrace();
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM