2017-11-03 1 views
0

메소드를 정의한 다음 ByteBuddy로 메소드를 여러 번 꾸밀 수있는 방법은 무엇입니까? 이 내 예입니다ByteBuddy를 사용하여 메소드 장식하기

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(); 
    } 

출력은

나는 출력이

실행 코드입니다 싶습니다 ... 다른 코드를 실행

입니다 .. .

실행 다른 코드 ...

감사

답변

1

하나의 옵션은 체인 MethodDelegation.to (...)를 사용하여 인터셉터입니다. addThen (...) 방법.

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..."); 
     } 
    } 
} 
+0

나는 여러 번 하위 클래스를 만들 수 없습니다. 인터셉터를 꾸미기 위해 데코레이터 패턴을 사용하겠습니다. 고맙습니다. – Marpa

+0

나는 본다. 귀하의 답변에 대한 대체 솔루션을 사용하여 답변을 업데이트했습니다. – kaos

0

저는 인터셉터를 꾸미기 위해 데코레이터 패턴을 사용합니다. 이제 예상대로 작동합니다. 내 솔루션을 공유 :

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(); 
    } 

} 
관련 문제