Writing a java annotation for timing method call

后端 未结 9 1386
逝去的感伤
逝去的感伤 2020-12-24 12:17

I want to write a java annotation which times the method call. something like this:

@TimeIt
public int someMethod() { ... }

and when this m

相关标签:
9条回答
  • 2020-12-24 12:40

    I am surprised to see that no one pointed out java.lang.reflect.Proxy. Its an old thread, but I think this information would be helpful to someone.

    Proxy has an interesting property which gives

    1. proxy instanceof Foo as true.
    2. You can have a method in your invocation handler, which prints the time first and then fires the actual method from the object.

    You can have this proxy for all objects by making them implement some interface or you can use Comparable.

    Look for section Dynamic proxies as decorator.

    http://www.ibm.com/developerworks/library/j-jtp08305/

    0 讨论(0)
  • 2020-12-24 12:42

    Simply put: you can't!

    Annotations are not pieces of code that get automatically started together with your code, they are just annotation, pieces of information that can be used by other programs working on your code like loading or running it.

    What you need is AOP: aspect oriented programming.

    0 讨论(0)
  • 2020-12-24 12:47

    Check out the Coda Hale Metrics library. It provides a @Timed annotation for methods that provides this capability. While you're at it check out Code Hale Dropwizard which has examples for how its been integrated into their service framework.

    @GET
    @Timed
    public Saying sayHello(@QueryParam("name") Optional<String> name) {
        return new Saying(counter.incrementAndGet(),
                          String.format(template, name.or(defaultName)));
    }
    
    0 讨论(0)
  • 2020-12-24 12:49

    Despite all the nay-sayers, you can do this. Java annotations cannot change the source or class files they operate on, so your options are:

    1) Use a super class. The annotation processor can generate a super-class that times an abstract method. Your actual class implements this method. The downsides is that the method you want to time has to be renamed so that the super-class can provide an implementation. The result might look like this

    @BenchmarkMe( extend="MySuperClass" )
    public class MyClass extends BenchmarkMyClass {
        public void normalMethod() { ... }
        public void bench_myMethod() { ... }
    }  
    

    and the annotation process would generate:

    public class BenchmarkMyClass extends MySuperClass {
        public abstract void bench_myMethod();
        public void myMethod() {
           benchmarkStart();
           try {
              bench_myMethod();
           } finally { benchmarkStop(); }
        }
    }
    

    By using a naming convention to indicate which methods should be timed as the prefix "bench_" was used in my example.

    2) Use a ClassFileTranformer as well as an Annotation The approach would be to create a runtime annotation that can be used to mark the methods you are interested in timing. At runtime a ClassFileTransformer is specified on the command line and it transforms the byte code to insert the timing code.

    Unless you like working with byte code, using AOP is the better bet, but it IS possible.

    0 讨论(0)
  • 2020-12-24 12:52

    It isn't nearly as easy in Java. The basic idea would be this:

    1. Create annotation that says "time this method"
    2. Create a java agent that uses byte code transformation to: a. Find methods with the annotation b. Add timing code to them
    3. Set the javaagent option when you run java to use your new agent

    This article would get you started: http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html .

    You might also be able to use BTrace to make this even easier: http://kenai.com/projects/btrace/pages/Home

    0 讨论(0)
  • 2020-12-24 12:54

    As of 2016, there's a nifty aspect annotation library jcabi-aspects.

    From the docs:

    Annotate your methods with @Loggable annotation and every time they are called, your SLF4J logging facility will receive a message with the details of execution and the total execution time:

    public class Resource {
      @Loggable(Loggable.DEBUG)
      public String load(URL url) {
        return url.openConnection().getContent();
      }
    }
    

    Something like this will appear in the log:

    [DEBUG] #load('http://www.google.com'): returned "<html ..." in 23ms
    

    Read more about @Loggable here.

    0 讨论(0)
提交回复
热议问题