编写java注解用于计时方法调用
我想写一个java注释来计时方法调用。像这样的事情:
@TimeIt
public int someMethod() { ... }
当调用这个方法时,它应该在控制台上输出这个方法花了多长时间
我知道如何在Python中做到这一点,这就是我想要它做的:
from time import time, sleep
def time_it(func):
def wrapper(*args, **kwargs):
start = time()
func(*args, **kwargs)
stop = time()
print "The function", func.__name__, " took %.3f" % (stop - start)
wrapper.__name__ = func.__name__
return wrapper
@time_it
def print_something(*args, **kwargs):
print "before sleeping"
print args, kwargs
sleep(3) # wait 3 seconds
print "after sleeping"
print_something(1, 2, 3, a="what is this?")
所以我的问题是? 我在哪里可以找到一些文档来编写这样的内容,我尝试了 apt
文档,没有运气。 有人可以帮忙写这样的东西吗?
I want to write a java annotation which times the method call. something like this:
@TimeIt
public int someMethod() { ... }
and when this method is invoked, it should output on console how long this method took
I know how to do it in python, this is what I want it to do:
from time import time, sleep
def time_it(func):
def wrapper(*args, **kwargs):
start = time()
func(*args, **kwargs)
stop = time()
print "The function", func.__name__, " took %.3f" % (stop - start)
wrapper.__name__ = func.__name__
return wrapper
@time_it
def print_something(*args, **kwargs):
print "before sleeping"
print args, kwargs
sleep(3) # wait 3 seconds
print "after sleeping"
print_something(1, 2, 3, a="what is this?")
So my questions are?
Where do I find some documentation to write something like this, I tried apt
documentation, had no luck with it.
can someone help with writing something like this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
AFAIK,Tomasz 说得对,这不能使用注释来完成。我认为这种混乱源于这样一个事实:Python 装饰器和 Java 注释共享相同的语法,但它们提供的行为完全不同!
注释是附加到您的类/方法/字段的元数据。 这篇博文地址使用AOP的点计时方法。尽管它使用 Spring,但基本前提保持不变。如果您擅长使用 AOP 编译器,那么翻译代码应该不会太困难。另一个参考(特定于 spring)此处。
编辑:如果您的目标是在不使用完整的分析器的情况下为应用程序提供总体方法计时,则可以使用 hprof 用于收集总执行统计信息。
AFAIK, Tomasz is right in saying that this can't be done using annotations. I think the confusion stems from the fact that Python decorators and Java annotations share the same syntax but are completely different in terms of the behavior they offer!
Annotations are metadata attached to your class/methods/fields. This blog post addresses the point of timing methods using AOP. Though it uses Spring, the basic premise remains the same. If you are good to go with an AOP compiler, it shouldn't be too difficult to translate the code. Another reference (spring specific) here.
EDIT: If your aim is to have a overall method timing for your application without using full blown profilers, you can use hprof for collecting total execution statistics.
简而言之:你不能!
注释不是与您的代码一起自动启动的代码片段,它们只是注释,是可以由处理您的代码的其他程序(例如加载或运行它)使用的信息片段。
你需要的是AOP:面向方面的编程。
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.
截至 2016 年,出现了一个漂亮的方面注释库 jcabi-aspects。
来自文档:
使用 @Loggable 注释来注释您的方法,每次调用它们时,您的 SLF4J 日志记录工具都会收到一条消息,其中包含执行详细信息和总执行时间:
类似这样的内容将出现在日志:
此处了解有关 @Loggable 的更多信息。
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:
Something like this will appear in the log:
Read more about @Loggable here.
我多次想知道同样的事情,并通过编写以下开始结束:
注释:
对象的接口:
调用处理程序:
最后是测试此的入口点:
这需要改进,因为它需要 Proxy 来实例化我们的对象,所以你不能真正将它用于“通用已编写”代码。
但它可能会让你得到更完整的东西。
I wondered the same thing several time and ended by writting the following start:
The annotation:
An object's interface:
An invocation handler:
An finally an entry point to test this:
This needs an improvement, since it requires Proxy to instantiate our object and so you can't really use it for "generic already written" code.
But it might leads you to something more complete.
查看 Coda Hale Metrics 库。它为提供此功能的方法提供了 @Timed 注释。当您使用它时,请查看Code Hale Dropwizard,其中包含有关如何将其集成到其服务框架中的示例。
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.
尽管有很多反对者,但你可以做到这一点。 Java 注释无法更改它们所操作的源文件或类文件,因此您的选择是:
1) 使用超类。注释处理器可以生成对抽象方法进行计时的超类。您的实际类实现了此方法。缺点是您想要计时的方法必须重命名,以便超类可以提供实现。结果可能如下所示
,注释过程将生成:
通过使用命名约定来指示应对哪些方法进行计时,因为我的示例中使用了前缀“bench_”。
2) 使用 ClassFileTranformer 以及 Annotation
该方法是创建一个运行时注释,可用于标记您感兴趣的计时方法。在运行时,在命令行上指定 ClassFileTransformer,它会转换字节代码以插入计时代码。
除非您喜欢使用字节代码,否则使用 AOP 是更好的选择,但它是是可能的。
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
and the annotation process would generate:
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.
我很惊讶地发现没有人指出 java.lang.reflect.Proxy。这是一个旧线程,但我认为这些信息会对某人有所帮助。
Proxy 有一个有趣的属性,它使
您可以通过使所有对象实现某个接口来为所有对象拥有此代理,或者您可以使用 Comparable。
查找动态代理部分作为装饰器。
http://www.ibm.com/developerworks/library/j-jtp08305/
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
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/
在 Java 中这并不那么容易。基本思想是这样的:
一个。查找带注解的方法
b.向它们添加计时代码
本文将帮助您入门:http://today.java.net/pub/a/today/2008/04/24/add- logging-at-class-load-time-with-instrumentation.html 。
您也许还可以使用 BTrace 来简化此操作:http://kenai.com/projects /btrace/pages/Home
It isn't nearly as easy in Java. The basic idea would be this:
a. Find methods with the annotation
b. Add timing code to them
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
如前所述,您不能,AOP 或 hprof 应该可以满足您的大部分需求,但如果您坚持使用 JSR269,可以找到解决方法。仅供参考,apt 已过时,并且注释处理 API 和工具已合并到 1.6 中(它的名称是令人回味的 JSR269)。
解决方法是创建一个注释处理器,该处理器生成一个类,该类扩展包含带有
@TimeIt
注释的方法的类。这个生成的类必须重写定时方法,它看起来像 Pythontime_it
但行func(*args, **kwargs)
将被super 替换.methodName(arg1, arg2, ...)
。然而,有两个警告:
As already stated you can't and AOP or hprof should cover most of your needs, but if you insist there's a workaround using JSR269. FYI, apt is obsolete and an annotation processing API and tool has been incorporated into 1.6 (and it is called with the evocative name JSR269).
The workaround would be to create an annotation processor that generates a class that extends the class that contains the method with the
@TimeIt
annotation. This generated class must override the timed method, it will look like the Pythontime_it
but the linefunc(*args, **kwargs)
would be replaced bysuper.methodName(arg1, arg2, ...)
.There are however two caveats: