2017-07-12 65 views
0

我們有一個模糊的類,我們需要使用bytebuddy進行增強。我們基本上需要重新定義一種方法。子類似乎沒有奏效(代碼沒有執行)。重新啓動工作,但在我們攔截的方法中,我們需要調用超類(現在像在「繼承」中講超類)方法。調用攔截器的超類方法bytebuddy

class Parent { 
    public void connect(){ 
    ... 
    }; 
} 

class WeNeedToHackThis extends Parent { 
    public void connect(InetAddress addr){ 
     //... this is what we want to hack 
    } 
    public void connect(){ 
     this.connect(null); 
     // this is getting called from interceptor :(which delegates to our hacked method 
     // we need to call "real" superclass's (Parent) method instead 
    } 

} 
... 
Class<?> dynamic = new ByteBuddy() 
      .with(TypeValidation.DISABLED) 
      .rebase(commandBase, locator) 
      .method(named("connect").and(takesArgument(0, InetAddress.class))) 
      .intercept(MethodDelegation.to(Session3270ConnectMethod.class)) 
      .make() 
      .load(Thread.currentThread().getContextClassLoader(), ClassLoadingStrategy.Default.INJECTION) 
      .getLoaded(); 

//In our interceptor: 
    public static void connect(InetAddress paramInetAddress, 
      @Origin Method origin, 
      @This Object self) throws SessionException { 
     try { 
      System.out.println("hi from hijacked"); 
      c.call(); 
      //HOW DO WE CALL SOMETHING LIKE super.connect() 
      // we need to call Parent.connect(); 
      // but I am stuck at how to access superclass code (new Parent().connect(). 
      // I cant access the Parent class method calls on this object 
      // if I use @SuperCall or @This then I am getting already overriden version, I need to call the super (Parent's.class) version :(

     } catch (Exception e) { 
      throw new RuntimeException(e); 

     } 
    } 
+0

好吧,我看到它沒有說清楚:) - 類Parent.class(這是父類,類WeNeedToHackThis從繼承的>「如何稱之爲‘連接()’方法 - 基本上,我們需要執行:'super.connect()'內部攔截器) – kosta5

回答

0
public static void connect(InetAddress paramInetAddress, 
      @Super Object parentObj, @This Object myself, @SuperCall Callable<?> call) throws SessionException { 
     try { 
      System.out.println("hi from hijacked"); 
      parentObj.getClass().getMethods(); 
      Field IMPL_LOOKUP = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP"); 
      IMPL_LOOKUP.setAccessible(true); 
      MethodHandles.Lookup lkp = (MethodHandles.Lookup) IMPL_LOOKUP.get(null); 
      MethodHandle h1 = lkp.findSpecial(b.class, "connect", MethodType.methodType(void.class), Session3270.class); 
      h1.invoke(myself); 
     } catch (Throwable e) { 
      throw new RuntimeException(e); 

     } 
    } 
0

如果我明白你的正確,你只想攔截一個方法調用,如果它是從你的類外部調用,但不是從內部調用。

這是一件很難實現的事情。 Byte Buddy允許您向任何類添加代碼,但即使手動添加代碼也很難編碼。

你最好的機會是可能添加一個線程本地存儲來標記這樣的自我調用,並檢測它是否攔截器被再次命中,你只需將其委託給super方法而不應用攔截器邏輯。

+0

其實我認爲我仍然在正確的措辭失敗......無論如何,我能夠解決它 - 看到我的答案調用父類下面(反射使用方法委託)。加入反射和bytebuddy,並實現了所需的東西。感謝一個真棒的lib壽! – kosta5

+0

啊,你有沒有試圖讓超級對象的父類型?這種方式,你可以直接調用方法! –

+0

我做了,這就是我以 結尾 java.lang.IllegalS tateException:大小= 0 \t在net.bytebuddy.matcher.FilterableList $ AbstractBase.getOnly(FilterableList.java:108) \t在net.bytebuddy.implementation.auxiliary.TypeProxy $ ForSuperMethodByConstructor.apply(TypeProxy.java:424) \t at net.bytebuddy.implementation.bind.MethodDelegationBinder $ ParameterBinding $ Anonymous.apply(MethodDelegationBinder.java:222) ... – kosta5