Вы заново изобретаете колесо, поскольку API журналирования уже существуют и способны идентифицировать метод.
Принимая встроенный API журналирования java.util.logging.*
, очень простым примером, демонстрирующим такую возможность, будет
public class MethodNameExample1 {
static final Logger MY_SERVICE = Logger.getAnonymousLogger();
static {
MY_SERVICE.setUseParentHandlers(false);
MY_SERVICE.addHandler(new Handler() {
public void publish(LogRecord lr) {
System.out.println(lr.getSourceClassName()+"."+lr.getSourceMethodName()
+" "+lr.getMessage()+"ed");
}
public void flush() {}
public void close() {}
});
}
public static void main(String[] args) {
MY_SERVICE.info("enter");
firstExample();
Inner.thirdExample();
MY_SERVICE.info("exit");
}
static void firstExample() {
MY_SERVICE.info("enter");
secondExample();
MY_SERVICE.info("exit");
}
static void secondExample() {
MY_SERVICE.info("enter");
MY_SERVICE.info("exit");
}
static class Inner {
static void thirdExample() {
MY_SERVICE.info("enter");
//...
MY_SERVICE.info("exit");
}
}
}
MethodNameExample1.main entered
MethodNameExample1.firstExample entered
MethodNameExample1.secondExample entered
MethodNameExample1.secondExample exited
MethodNameExample1.firstExample exited
MethodNameExample1$Inner.thirdExample entered
MethodNameExample1$Inner.thirdExample exited
MethodNameExample1.main exited
Если вы хотите иметь больше контроля над этим (или настаивать на создании собственной реализации API ведения логов), Java 9 * StackWalker
- это путь к go. В отличие от захвата трассировки стека, как при new Throwable().getStackTrace()
, обходчик стека поддерживает извлечение только необходимой информации, включая подсказки о максимальном количестве кадров, которые мы собираемся пройти, поэтому JVM не нужно обрабатывать больше, чем необходимо, и может применяться в дальнейшем оптимизации:
public class MethodNameExample2 {
public static class MyService {
private static final StackWalker STACK_WALKER=StackWalker.getInstance(Set.of(), 3);
public static void enter() {
System.out.println(getCaller()+" entered");
}
public static void exit() {
System.out.println(getCaller()+" exited");
}
private static String getCaller() {
return STACK_WALKER.walk(frames -> frames.skip(2)
.map(f -> f.getClassName()+'.'+f.getMethodName())
.findFirst().orElse("unknown caller"));
}
}
public static void main(String[] args) {
MyService.enter();
firstExample();
Inner.thirdExample();
MyService.exit();
}
static void firstExample() {
MyService.enter();
secondExample();
MyService.exit();
}
static void secondExample() {
MyService.enter();
MyService.exit();
}
static class Inner {
static void thirdExample() {
MyService.enter(); MyService.exit();
}
}
}
MethodNameExample2.main entered
MethodNameExample2.firstExample entered
MethodNameExample2.secondExample entered
MethodNameExample2.secondExample exited
MethodNameExample2.firstExample exited
MethodNameExample2$Inner.thirdExample entered
MethodNameExample2$Inner.thirdExample exited
MethodNameExample2.main exited