Tobias Hilka
Tobias Hilka

Reputation: 273

How do I intercept a method invocation with standard java features (no AspectJ etc)?

I want to intercept all method invocations to some class MyClass to be able to react on some setter-invocations.

I tried to use dynamic proxies, but as far as I know, this only works for classes implementing some interface. But MyClass does not have such an interface.

Is there any other way, besides implementing a wrapper class, that delegates all invocations to a member, which is an instance of the MyClass or besided using AOP?

Upvotes: 23

Views: 54430

Answers (7)

Nick Fortescue
Nick Fortescue

Reputation: 44173

If you are prepared to do something really ugly, have a look at:

http://docs.oracle.com/javase/7/docs/technotes/guides/jpda/

Basically the debugger interface ought to allow you to attach like a debugger, and hence intercept calls. Bear in mind I think this is a really bad idea, but you asked if it was possible.

Upvotes: 14

eljenso
eljenso

Reputation: 17027

As you note, you cannot use JDK dynamic proxies (no interface), but using Spring and CGLIB (JAR included with Spring), you can do the following:

public class Foo
{
    public void setBar()
    {
        throw new UnsupportedOperationException("should not go here");
    }

    public void redirected()
    {
        System.out.println("Yiha");
    }
}

Foo foo = new Foo();
ProxyFactory pf = new ProxyFactory(foo);

pf.addAdvice(new MethodInterceptor()
{
    public Object invoke(MethodInvocation mi) throws Throwable
    {
        if (mi.getMethod().getName().startsWith("set"))
        {
            Method redirect = mi.getThis().getClass().getMethod("redirected");
            redirect.invoke(mi.getThis());
        }
        return null;
    }
});

Foo proxy = (Foo) pf.getProxy();
proxy.setBar(); // prints "Yiha"

Upvotes: 30

Pierantonio
Pierantonio

Reputation: 27

I just developed a small framework for this purpose. You can check it out at: http://code.google.com/p/java-interceptor/ (use svn to check out).

Upvotes: 1

Gareth Davis
Gareth Davis

Reputation: 28059

Java doesn't have any actual language features for method interception (not sure any static language does)

I kinda like Nick's idea of using the debugger interface, that's just mean.

I think the short answer you need is: No there isn't a way of intercepting a method call in Java without actually replacing the class using a proxy or wrapper.

Note: The AOP libraries just make this happen automatically.

Upvotes: 3

Stas
Stas

Reputation: 1059

  1. Why cannot your class implement an interface? You could just extract some interface from it containing all the methods that you want to intercept and use the dynamic proxies mechanism easily. It's also a good programming practice to code with interfaces and not classes.

  2. You could use Spring framework with Spring AOP capabilities (which are using dynamic proxies inside) to do it. You will just have to define your class as a Spring bean in the configuration file and clients of your class will have to either get its instance from the Spring application context or as a dependency automatically (by defining the setMyClass(MyClass mc) method for instance). From there you can easily go to defining an aspect that intercepts all the method calls to this class.

Upvotes: 0

Aaron Digulla
Aaron Digulla

Reputation: 328604

Some of the Java gurus might frown upon this but I've had some good success with avoiding primitive types and setters altogether. My class looks like this:

class Employee extends SmartPojo {
    public SmartString name;
    public SmartInt age;
}

You'll notice two things: 1. everything is public. 2. No constructor.

The magic happens in SmartPojo which searches for any field which implements the "Smart" interface and initializes it. Since this is no primitive (and no final class), I can add set() and get() methods for all fields anywhere in my model in a single place. So no setter/getter wastes anymore, it's stunningly simple to add notification (also in a single place), etc.

True, this is no POJO anymore and it's not a Bean in most ways but I've found that these old ideas limit me more than they help. YMMV.

Upvotes: 1

Miserable Variable
Miserable Variable

Reputation: 28752

There isn't a lot of magic in AspectJ. You can write your own agent. http://java.sun.com/javase/6/docs/api/java/lang/instrument/package-summary.html seems to be good starting point.

Upvotes: 0

Related Questions