Java - “拦截”一个私有方法

本·莱特纳

我知道以前有人问过这个问题,答案通常是“你不能”和/或“不要”,但无论如何我都在尝试。

上下文是我试图设置一些“黑魔法”来帮助测试。我的代码最终在 JUnit 下运行,并且系统的性质是这样的,虽然我可以访问我想要的大多数库(ByteBuddy、Javassist 等),但我无法在代码运行之前玩弄它,我一直在忙着上课。

这是设置:

// External Library that I have no control over:
package com.external.stuff;

/** This is the thing I ultimately want to capture a specific instance of. */
public class Target {...}

public interface IFace {
  void someMethod();
}

class IFaceImpl {
  @Override  
  void someMethod() {
     ...
     Target t = getTarget(...);
     doSomethingWithTarget(t);
     ...
  }

  private Target getTarget() {...}
  private void doSomethingWithTarget(Target t) {...}
}

在我的测试魔法中,我有一个 IFace 实例,我碰巧知道它是一个 IFaceImpl。什么我喜欢做的是能够窃取的实例Target内部产生。实际上,这将具有与以下相同的效果(如果私有方法是可覆盖的):

class MyIFaceImpl extends IFaceImpl{
  private Consumer<Target> targetStealer;

  @Override  
  void someMethod() {
     ...
     Target t = getTarget(...);
     doSomethingWithTarget(t);
     ...
  }

  /** "Override" either this method or the next one. */
  private Target getTarget() {
    Target t = super.getTarget();
    targetStealer.accept(t);
    return t;
  }

  private void doSomethingWithTarget(Target t) {
    targetStealer.accept(t);
    super.doSomethingWithTarget(t);
  }
}

但是,当然,这不起作用,因为私有方法不能被覆盖。因此,下一种方法将类似于ByteBuddyJavassist

public static class Interceptor {
  private final Consumer<Target> targetStealer;
  // ctor elided

  public  void doSomethingWithTarget(Target t) {
    targetStealer.accept(t);
  }
}


/** Using ByteBuddy. */
IFace byteBuddyBlackMagic(
    IFace iface /* known IFaceImpl*/,
    Consumer<Target> targetStealer) {
  return (IFace) new ByteBuddy()
      .subClass(iface.getClass())
      .method(ElementMatchers.named("doSomethingWithTarget"))
      .intercept(MethodDelegation.to(new Interceptor(t))
      .make()
      .load(...)
      .getLoaded()
      .newInstance()
}

/** Or, using Javassist */
IFace javassistBlackMagic(
    IFace iface /* known IFaceImpl*/,
    Consumer<Target> targetStealer) {
  ProxyFactory factory = new ProxyFactory();
  factory.setSuperClass(iface.getClass());
  Class subClass = factory.createClass();
  IFace = (IFace) subClass.newInstance();

  MethodHandler handler =
      new MethodHandler() {
        @Override
        public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
          if (thisMethod.getName().equals("doSomethingWithTarget")) {
            consumer.accept((Target) args[0]);
          }
          return proceed.invoke(self, args);
        }
      };
  ((ProxyObject) instance).setHandler(handler);
  return instance;
}

当我测试这些模式时,它在我想要拦截的方法是包本地的其他情况下工作,但不适用于私有方法(预计 ByteBuddy,根据文档)。

所以,是的,我认识到这是试图调用黑暗力量,这通常是不受欢迎的。问题仍然存在,这可行吗?

使用 javassist,您可以检测 IClassImpl 类中的 someMethod() 以将 TargetClass 的实例发送到其他类并将其存储在那里或使用创建的实例进行其他操作。

这可以使用 javassist 中的 insertAfter() 方法来实现。

例如 :

method.insertAfter( "TestClass.storeTargetInst(t)" ); // t is the instance of Target class in IClassImpl.someMethod

TestClass{ public static void storeTargetInst(Object o){ ### code to store instance ###} }

insertAfter() 方法在方法的 return 语句之前或在 void 方法的情况下作为方法的最后一行注入一行代码。

有关可用于仪器的方法的更多信息,请参阅此链接希望这可以帮助!

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

测试内部使用Java中另一个私有静态方法的私有静态方法

来自分类Dev

解决打字稿的另一个私有方法中的函数内私有方法调用的范围

来自分类Dev

在任何测试步骤之前,在每个JUnit中调用一个私有方法

来自分类Dev

Java私有方法包装

来自分类Dev

Java继承中的私有方法

来自分类Dev

Java继承中的私有方法

来自分类Dev

我如何才能在自己的类中制作一个私有方法,以便一遍又一遍地使用

来自分类Dev

我如何才能在自己的类中制作一个私有方法,以便一遍又一遍地使用

来自分类Dev

具有许多私有方法的Java测试类

来自分类Dev

Java私有方法“返回”或“设置值”

来自分类Dev

Java接口中的公共/私有方法签名

来自分类Dev

使用Powermockito在Java中测试私有方法

来自分类Dev

在另一个私有void方法中使用查询结果

来自分类Dev

Java为什么不允许我通过同一类的方法访问私有方法?

来自分类Dev

在私有方法中动态创建一个公共方法

来自分类Dev

为什么在java.util.ArrayList中有私有方法outOfBoundsMsg?

来自分类Dev

Java中带有上调调用的“覆盖”私有方法

来自分类Dev

使用Java / Mockito / PowerMockito用私有构造函数实例化一个类

来自分类Dev

如何从另一个对象修改对象的私有ArrayList属性(Java)

来自分类Dev

从Java中的另一个类访问私有变量

来自分类Dev

为什么从另一个类执行此私有方法?

来自分类Dev

从私有方法中的另一个类访问对象

来自分类Dev

当类只有一个私有构造函数时,如何创建代理?

来自分类Dev

OpenACC:每个 GPU 线程都有一个私有数组

来自分类Dev

此私有方法在此Singleton Java类中做什么?

来自分类Dev

动态绑定如何对Java基类中的私有方法起作用?

来自分类Dev

如何在Java类中修改或替换私有方法

来自分类Dev

使用java.lang.invoke.MethodHandle调用私有方法

来自分类Dev

为什么Java中的私有方法是隐式最终的?

Related 相关文章

  1. 1

    测试内部使用Java中另一个私有静态方法的私有静态方法

  2. 2

    解决打字稿的另一个私有方法中的函数内私有方法调用的范围

  3. 3

    在任何测试步骤之前,在每个JUnit中调用一个私有方法

  4. 4

    Java私有方法包装

  5. 5

    Java继承中的私有方法

  6. 6

    Java继承中的私有方法

  7. 7

    我如何才能在自己的类中制作一个私有方法,以便一遍又一遍地使用

  8. 8

    我如何才能在自己的类中制作一个私有方法,以便一遍又一遍地使用

  9. 9

    具有许多私有方法的Java测试类

  10. 10

    Java私有方法“返回”或“设置值”

  11. 11

    Java接口中的公共/私有方法签名

  12. 12

    使用Powermockito在Java中测试私有方法

  13. 13

    在另一个私有void方法中使用查询结果

  14. 14

    Java为什么不允许我通过同一类的方法访问私有方法?

  15. 15

    在私有方法中动态创建一个公共方法

  16. 16

    为什么在java.util.ArrayList中有私有方法outOfBoundsMsg?

  17. 17

    Java中带有上调调用的“覆盖”私有方法

  18. 18

    使用Java / Mockito / PowerMockito用私有构造函数实例化一个类

  19. 19

    如何从另一个对象修改对象的私有ArrayList属性(Java)

  20. 20

    从Java中的另一个类访问私有变量

  21. 21

    为什么从另一个类执行此私有方法?

  22. 22

    从私有方法中的另一个类访问对象

  23. 23

    当类只有一个私有构造函数时,如何创建代理?

  24. 24

    OpenACC:每个 GPU 线程都有一个私有数组

  25. 25

    此私有方法在此Singleton Java类中做什么?

  26. 26

    动态绑定如何对Java基类中的私有方法起作用?

  27. 27

    如何在Java类中修改或替换私有方法

  28. 28

    使用java.lang.invoke.MethodHandle调用私有方法

  29. 29

    为什么Java中的私有方法是隐式最终的?

热门标签

归档