views:

22

answers:

3

Hi, basically what i'm trying to do is to load dynamically a class with annotated methods, run the main method of the class then trigger some code when the annotated methods are called.

Exemple :

public myclass {
public static void myMethod1(){
mymethod2();
}

@trace
public static void myMethod2(){
   ... some code here ...
}
public static void main(String[] args) {
mymethod1();
}
}

the traceHandler.java program should be able to load any class, run its main method and print a "Method X called" when an annotated X method is called. i did the dynamic loading part but i can't find a way to "place listners" on the annotated methods.

The solutions that i've found involve using AOP or using proxies by making the target classes implement some interfaces (1) is there any other way to do the whole thing dynamically without getting into the details of the target class ?

+1  A: 

You can use AspectJ for tracing the methods calls. Create pointcuts to target methods annotated with your @trace annotation and create joinpoints to catch the execution of those methods. Then you can write advice in which you can log the method calls to sysout or a log file. See this blog post for an example.

abhin4v
A: 

Creating a dynamic proxy does not require you to go into the detail of the target class as all the information you need is passed in the call to invoke().

Check out http://java.sun.com/j2se/1.4.2/docs/guide/reflection/proxy.html It is not as scary as it sounds.

I am a bit confused about the problem of the target classes not implementing interfaces. If you are going to load them dynamically they need to fit somehow in the bigger picture and I always assume there is some interface to be able to manipulate them.

Peter Tillemans
+1  A: 

Using dynamic proxy is to my knowledge the simplest way to "enrich" the behavior of a class with annotations without resorting to instrumentation or third-party frameworks.

The InvocationHandler can be completely generic though, it doesn't need knowledge of the target class. The example in you link has

private final Login realLogin;

but that could well be replaced by

private final Object realLogin;

because the invocation happens with return method.invoke(realLogin, args);.

Note that you won't be able to use this technique with static method, like in your question. The technique works indeed only on instance methods, and if the object implements an interface.

ewernli