Есть ли простой способ получить и отправить `имя текущего метода` в качестве аргумента в java? - PullRequest
2 голосов
/ 09 января 2020

Создание API для регистрации и предоставления общих методов.

public static void start(Class<?> clazz) throws IOException {
    writeExecutionLog("Start of" + clazz.getName(), null);
}

public static void end(Class<?> clazz) throws IOException {
    writeExecutionLog("End of" + clazz.getName(), null);
}

В классах есть несколько планировщиков в разных методах, которые вызывают выше начала и конца при запуске или завершении работы.

class scheduler{

 public void scheduler1(){
    MyService.start(methodname or class)
    MyService.end(methodname or class)
 }

 public void scheduler2(){
    MyService.start(methodname or class)
    MyService.end(methodname or class)
 }
}

Вместо String есть какой-нибудь простой способ передать имя метода вместе с именем класса в начальный и конечный метод выше.

Я хочу динамически извлекать имя текущего метода в методах Start и end что-то вроде this.class.currentMethod? (Не сложное утверждение, подобное упомянутому в geekofgeeks, и лучше, если я смогу обрабатывать большинство вещей в start () и end ())

Ответы [ 4 ]

3 голосов
/ 09 января 2020

Вы можете сгенерировать трассировку стека и проанализировать строку. Это универсально, но дорого.

public static void start() throws IOException {
    writeExecutionLog("Start of" + new Throwable().getStackTrace()[1].getMethodName(), null);
}
2 голосов
/ 09 января 2020
String methodName = new Object() {}
  .getClass()
  .getEnclosingMethod()
  .getName();

в вашем методе должно работать.

1 голос
/ 09 января 2020

Вы заново изобретаете колесо, поскольку 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
0 голосов
/ 09 января 2020

Ваша задача должна выполняться с использованием AOP (Аспектно-ориентированное программирование).

[AOP] направлен на повышение модульности, позволяя разделить сквозные задачи. Это достигается путем добавления дополнительного поведения к существующему коду (рекомендации) без изменения самого кода, вместо этого отдельно указывается, какой код изменяется с помощью спецификации "pointcut", такой как ", регистрируя все вызовы функций, когда имя функции начинается с 'set' '.

Например, вы можете пометить все ваши методы планировщика пользовательской аннотацией (или использовать имя метода, имя пакета и т. д. c.) и создать аспект.

@Around("@annotation(LogExecutionTime)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
   logger.debug("start of ...")
   Object proceed = joinPoint.proceed();
   logger.debug("end of ...")
   return proceed;
}

из ProceedingJoinPoint Вы можете извлечь много информации, а не только имя метода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...