0

所以,假设我有 2 个类,Foo1 和 Foo2,它们位于一个单独的库中。

Foo2 是一个已经实例化的类,我无法正确地将其重新设置为子类以覆盖 Foo2 中的方法。

有什么方法可以让我监听 Foo2 中调用的某个方法,然后可能取消该方法的执行,然后从那里创建另一个方法。我理解我所说的是否令人困惑,希望我能得到一些帮助:)。

    class Foo{

    void x(){
    if (Foo2.x2().called){
    //do stuff
    }
    }
    }

    class Foo2{
    void x2(){
    //Stuff done here...
    }
    }

显然,上面的代码不会做任何事情,它只是我正在寻找的一个简单示例。

4

5 回答 5

5

您需要该对象上的代理和方法上的拦截器。有几种方法可以做到:

  1. 如果您有接口,则可以使用反射和代理以及调用处理程序 docs.oracle.com/javase/6/docs/api/java/lang/reflect/Proxy.html。

  2. 如果你有一个具体的类,你可以使用 CGLIB cglib.sourceforge.net 为你的类创建一个增强器

  3. 如果您使用 Spring,则可以使用 AOP http://static.springsource.org/spring/docs/2.5.5/reference/aop.html

  4. 您也可以使用 AspectJ http://www.eclipse.org/aspectj/doc/next/progguide/来做同样的事情

    干杯!

于 2013-07-11T00:54:27.723 回答
4

如果你不能以某种方式继承 Foo2 或修改现有的库(在最坏的情况下你可以反编译/修改/重新编译),你可以使用 aspectj 来拦截调用。

为此,您可能希望使用加载时编织。在此处查看加载时编织的一般文档:http: //www.eclipse.org/aspectj/doc/next/devguide/ltw.html。这是一个相当复杂的添加/配置 aspectj 的过程,所以我只推荐它作为最后的手段

于 2013-07-11T00:45:26.550 回答
0

在我看来,要解决这个问题,您可以使用第三个类来充当装饰器/代理。

例如,您可以执行以下操作:

class FooManager {

  private Foo1 f1;

  private Foo2 f2;

  private boolean canExecuteFooMethods(){
     // Evaluate if should run any Foo1 or Foo2 method
  }
  public void foo1Method(){
    if(canExecuteFooMethods()){
      f1.x();
    }
  }

  public void foo2Method(){
    if(canExecuteFooMethods()){
      f2.x();
    }
  }
}
于 2013-07-11T00:50:15.773 回答
0

根据您要执行的操作,这可能会起作用:

如果您在类 Foo 中有一个布尔 isX2Called,当调用 x2() 时,将 isX2Called 设置为 true。然后在 x() 中,您可以检查 isX2Called 是否为真。如果您想重置,可以将 isX2Called 设置回 false。不过,这可能不适用于所有目的。

于 2013-07-11T00:51:32.777 回答
0

假设您可以对类型进行子类化,以下代码将完美运行:

Foo foo = new Foo() {

    @Override
    public void someMethod() {
        super.someMethod();
        //your logic here (listen, hook, spy, override, etc)
    }
}
于 2020-10-07T13:42:40.870 回答