Java:获取当前正在执行的Method对应的对象

发布于 2024-10-19 09:50:59 字数 143 浏览 0 评论 0原文

将当前正在执行的方法作为 Method 对象获取的最优雅的方法是什么?

我的第一个明显的方法是在辅助类中使用静态方法,该方法将加载当前线程堆栈,获取正确的堆栈跟踪元素,并根据其信息构造 Method 元素。

有没有更优雅的方法来实现这一点?

What is the most elegant way to get the currently executing method as a Method object ?

My first obvious way to do it would be to use a static method in a helper class, which would load the current thread stack, get the right stack trace element, and construct the Method element from its information.

Is there a more elegant way to achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

看海 2024-10-26 09:50:59

在此问题中更深入地介绍了该主题。

我需要做同样的事情,我发现最好的解决方案是@alexsmail 提供的解决方案。

这看起来有点老套,但总体思路是在方法中声明一个本地类,然后利用 class.getEnlookingMethod();

代码对 @alexsmail 的解决方案进行了稍微修改:

public class SomeClass {
   public void foo(){
      class Local {};
      Method m = Local.class.getEnclosingMethod();
   }
 }

This topic is covered in deeper depth in this SO Question.

I need to do the same thing and I found the best solution to be the one provided by @alexsmail.

It seems a little bit hacky but the general idea is that you declare a local class in the method and then take advantage of class.getEnclosingMethod();

Code slightly modified from @alexsmail's solution:

public class SomeClass {
   public void foo(){
      class Local {};
      Method m = Local.class.getEnclosingMethod();
   }
 }
歌入人心 2024-10-26 09:50:59

开箱即用,我不知道有更好的方法来做到这一点。

也许需要考虑的一件事是方面 - 您可以将一个方面编织到围绕所有方法调用触发的代码中,并将当前的 Method 对象推送到 ThreadLocal (基于从连接点可用的反射信息) 。

如果它真的在所有方法上触发,这可能会非常昂贵,但是根据您对结果所做的操作,您可能能够将捕获限制为某些包/类,这将帮助。您也可以推迟 Method 的实际查找,直到使用它为止,而是存储方法的名称和参数等。

我怀疑是否会有一个特别的不过,实现这一目标的廉价方法。

Out of the box, I'm not aware of a better way to do this.

One thing to consider perhaps would be aspects - you could weave an aspect into the code that fired around all method invocations and pushed the current Method object to a ThreadLocal (based on the reflective information available from the joinpoint).

This would be probably prohibitively expensive if it really fired on all methods, but depending on what you're doing with the results, you may be able to constrain the capturing down to certain packages/classes, which would help. You may be able to defer the actual lookup of the Method too until such time as it's used, and instead store the name of the method and arguments etc.

I have my doubts whether there's going to be a particularly cheap way to achieve this, though.

梦亿 2024-10-26 09:50:59

我发现这很有效:

package com.paintedintel.util;

public class Log{

    public static void out(final String output) {
        System.out.println(output);
    }
    
    public static void debug(String output) {
        System.err.println(Log.currentLocation() + " " + output);
    }
    
    public static String currentLocation() {
        StackTraceElement classMethod = new Throwable() 
                .getStackTrace()[2];
        String   currMethod = classMethod.getMethodName(); 
        String   fullClass  = classMethod.getClassName();
        String[] smplClass  = fullClass.split("\\.");
        return smplClass[smplClass.length - 1] + "." + currMethod;
    }   
}

您可以调用它,因为

Log.debug("my message " + myParameters);

我打印出 simpleClassName() 而不是您无法直接获取的包类名称,即

split("\\."); //是的,您需要转义“.”

除此之外,它可以自动跟踪您的调试输出来自何处。或者您可以使用它来获取方法和类名称。

如果您结合 debug 和 currentLocation 方法,您将不得不使用较低的索引来获取您想要的行......

        StackTraceElement classMethod = new Throwable() 
                .getStackTrace()[2]; // use a different index [x] w/exr methods

I find that this works well:

package com.paintedintel.util;

public class Log{

    public static void out(final String output) {
        System.out.println(output);
    }
    
    public static void debug(String output) {
        System.err.println(Log.currentLocation() + " " + output);
    }
    
    public static String currentLocation() {
        StackTraceElement classMethod = new Throwable() 
                .getStackTrace()[2];
        String   currMethod = classMethod.getMethodName(); 
        String   fullClass  = classMethod.getClassName();
        String[] smplClass  = fullClass.split("\\.");
        return smplClass[smplClass.length - 1] + "." + currMethod;
    }   
}

You can call it as

Log.debug("my message " + myParameters);

I have it printing out the simpleClassName() rather than the package class name which you can't get at directly which is the

split("\\."); //yes you need to escape the "."

Other than that, it can track where you're debug output is coming from automatically. Or you could just use it to get the method and class names.

If you combine the debug and currentLocation methods you'll have to use a lower index to get the line you want....

        StackTraceElement classMethod = new Throwable() 
                .getStackTrace()[2]; // use a different index [x] w/exr methods
很酷又爱笑 2024-10-26 09:50:59

如果您使用的是 Java 9+,那么您可以使用 StackWalker:

public void foo() {
    StackWalker walker = StackWalker.getInstance();
    Optional<StackTraceElement> stackTraceElement = walker.walk(frames -> frames
            .findFirst()
            .map(StackWalker.StackFrame::toStackTraceElement));
    
    if (stackTraceElement.isPresent()) {
        // from here you can construct the method being called
        // the same way as you would with the other methods mentioned
    }
}

此方法的优点是每个 StackTraceElement 都是延迟获取,因此您不必'在检查第一个方法之前,实际上会构建完整的堆栈跟踪。

If you are using Java 9+ then you can use StackWalker:

public void foo() {
    StackWalker walker = StackWalker.getInstance();
    Optional<StackTraceElement> stackTraceElement = walker.walk(frames -> frames
            .findFirst()
            .map(StackWalker.StackFrame::toStackTraceElement));
    
    if (stackTraceElement.isPresent()) {
        // from here you can construct the method being called
        // the same way as you would with the other methods mentioned
    }
}

The advantage of this method is that each StackTraceElement is fetched lazily so you don't actually construct the full stack trace before checking the first method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文