2017-07-12 63 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