views:

61

answers:

2

I've never written an annotation in Java.

I've got a simple Java class for performance measurement. I call it PerfLog. Here's an example of its use:

public class MyClassToTest {
  public String MyMethod() {
    PerfLog p = new PerfLog("MyClassToTest", "MyMethod");
    try {
       // All the code that I want to time.
       return whatever;
    } finally {
       p.stop();
    }
  }
}

When p.stop() is called, a line will be written to the log file:

2010/10/29T14:30:00.00 MyClassToTest MyMethod elapsed time: 00:00:00.0105

Can PerfLog be rewritten as an Annotation so that I can write this instead?

public class MyClassToTest {
  @PerfLog
  public String MyMethod() {
    // All the code I want to time.
    return whatever;
  }
}

It would seem to be a good candidate for annotating: It's easy to add or take away the annotation; a production build can leave out PerfLog entirely without having to remove the annotations from the source code; the annotation processor can get the class and method names.

Is this easy to do? Is there a recipe somethere that I can follow?

It has to be Java 5 so I know I have to use apt somewhere.

+1  A: 

Consider using AOP or Spring - supports Annotations to intercept method invocations and implement custom code

In case that sounds interesting, the Spring AOP docs are here : http://static.springsource.org/spring/docs/2.5.x/reference/aop.html

You can definitely write the annotation parser and its runtime implementation on your own, but reinventing will only be error prone and inefficient when compared to industry solutions.

If you insist on implementing this on your own (without AOP or AOP with Spring), here is what I can suggest (may not be the bestest method) :

  1. Create your beans via a custom FactoryBean always.
  2. In the custom FactoryBean implementation, query the class for methods and check if they are annotated.
  3. If yes, instead of returning the instance of the class itself, return a proxy over the instance.
  4. In the invoke of this proxy, wrap the call to the actual instance's method with new PerfLog() and p.stop()

Its effectively what AOP would (more powerfully) do for you. However, take note that final classes, static methods, classes with no interfaces etc.. will still be a problem in this case (a different ball game).

madhurtanwani
Adding a framework like Spring is not a viable option in this case.
Mark Lutton
AspectJ can also do this, other than requiring the runtime side of aspectj there is no other overhead.
vickirk
edited answer with a possible implementation. Would still recommend considering AOP or AOP via Spring - its not that heavy weight.
madhurtanwani
+1  A: 

There is no trivial way to do this using standard Java tools. The path of least resistance would almost certainly be to use an AOP-style library like Google Guice or Spring or AspectJ. Any home-grown attempt to solve this problem will essentially end up doing what AOP libraries would already do for you.

Mike Clark