0

So, let's say I have 2 classes, Foo1 and Foo2, which is in a separate library.

Foo2 is a class that is already instantiated, and I cannot correctly reinstintate it as a subclass to override a method in Foo2.

Is there any way I can listen to a certain method that is called in Foo2, and then possibly cancel the execution of said method, and from there create another method. I understand if what I"m saying is confusing, hopefully I can get some help :).

    class Foo{

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

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

Obviously, the above code won't do anything, it is just simple an example of what I am looking for.

dillyg10
  • 13
  • 6
  • Any chance you can show some code to give us a better idea of what you want to do? Also, where does `Foo1` come into play? – arshajii Jul 11 '13 at 00:35
  • Alrighty, well I can't give too much of a hard example, not because I don't want to give code... but because it has to do with a funky lib, anyways, let me quickly edit the above post so show what i'm talking about. – dillyg10 Jul 11 '13 at 00:38
  • Utilize this: http://stackoverflow.com/questions/442747/getting-the-name-of-the-current-executing-method –  Jul 11 '13 at 00:42

5 Answers5

5

you need a proxy on that object, and an interceptor on the method. There are a couple of ways to do it:

  1. If you have an interface you can use reflection and proxies and invocation handlers docs.oracle.com/javase/6/docs/api/java/lang/reflect/Proxy.html.

  2. If you have a concrete class you can use CGLIB cglib.sourceforge.net to create an enhancer for your class

  3. If you are using Spring you can use the AOP http://static.springsource.org/spring/docs/2.5.5/reference/aop.html.

  4. You can also use AspectJ http://www.eclipse.org/aspectj/doc/next/progguide/ to do the same

    Cheers!

Community
  • 1
  • 1
Totò
  • 1,824
  • 15
  • 20
  • I'm wondering if you might be willing to give an example using CGLIB, I looked through the docs, and I'm just a tad confused. Thanks ;) – dillyg10 Jul 11 '13 at 11:02
4

If you can't somehow subclass Foo2 or modify the existing lib (in worst case you could decompile/modify/recompile) you could use aspectj to intercept calls.

You'd probably want to use load-time weaving for this purpose. Check out the general documentation for load-time weaving here: http://www.eclipse.org/aspectj/doc/next/devguide/ltw.html. It's a fairly involved procedure to add/configure aspectj though so I'd only recommend it as a last resort

0

In my opinion, to solve this issue you could use a third class to act as a Decorator/Proxy.

For instance, you can do something like:

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();
    }
  }
}
Rafa
  • 1,997
  • 3
  • 21
  • 33
0

Depending on what you're trying to do, this might work:

If you had a boolean isX2Called in class Foo, when x2() is called, set isX2Called to true. Then in x(), you can check if isX2Called is true. If you ever want to reset, you can set isX2Called back to false. This might not work for all purposes though.

user2570465
  • 2,437
  • 2
  • 18
  • 22
0

Assuming that you can subclass the type, the following code would work perfectly:

Foo foo = new Foo() {

    @Override
    public void someMethod() {
        super.someMethod();
        //your logic here (listen, hook, spy, override, etc)
    }
}
valijon
  • 1,304
  • 2
  • 20
  • 35