Измерение повторного использования методов

Мне нужно подсчитать, сколько раз вызывается какой-либо метод в конкретном пакете (аналогично Hieracy, но во время выполнения, чтобы экспортировать результаты).

Например: Метод setA вызывается 17 раз, метод setB вызывается 3 раза...

Основываясь на этом ответе, мне удалось извлечь все методы из классов реализации, но я не знаю, как найти все варианты их использования в рабочем коде.

public static List<Class<?>> find(String scannedPackage) {
    String scannedPath = scannedPackage.replace(PKG_SEPARATOR, DIR_SEPARATOR);
    URL scannedUrl = Thread.currentThread().getContextClassLoader().getResource(scannedPath);
    if (scannedUrl == null) {
        throw new IllegalArgumentException(String.format(BAD_PACKAGE_ERROR, scannedPath, scannedPackage));
    }
    File scannedDir = new File(scannedUrl.getFile());
    List<Class<?>> classes = new ArrayList<Class<?>>();
    for (File file : scannedDir.listFiles()) {
        classes.addAll(find(file, scannedPackage));
    }
    return classes;
}

private static List<Class<?>> find(File file, String scannedPackage) {
    List<Class<?>> classes = new ArrayList<Class<?>>();
    String resource = scannedPackage + PKG_SEPARATOR + file.getName();
    if (file.isDirectory()) {
        for (File child : file.listFiles()) {
            classes.addAll(find(child, resource));
        }
    } else if (resource.endsWith(CLASS_FILE_SUFFIX)) {
        int endIndex = resource.length() - CLASS_FILE_SUFFIX.length();
        String className = resource.substring(0, endIndex);
        if (className.endsWith("ActivityImpl")) {
            try {
                classes.add(Class.forName(className));
            } catch (ClassNotFoundException ignore) {
            }
        }

    }
    return classes;
}

и используйте его следующим образом:

public static void main(String[] args) throws Exception {
    List<Class<?>> classes = find("com.my.project.activities");
    for (Class c : classes) {
        System.out.println("Class name: " + c.getName());
        System.out.print("Methods: ");
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            System.out.print(method.getName() + ", ");
        }
        System.out.println();
        System.out.println();
    }
}

как я могу подсчитать использование каждого метода?

Дополнительная информация: Java 21, Spring Boot 3.2.4.

Похоже, вам нужен профайлер

Mureinik 02.06.2024 09:38
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
1
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Лучший способ подсчета вызовов методов — использование аспектов. См. https://docs.spring.io/spring-framework/docs/4.3.15.RELEASE/spring-framework-reference/html/aop.html Аспектно-ориентированное программирование поначалу кажется трудным, но оно дает вам свободу в действиях и, что более важно, оставляет ваши методы нетронутыми. Вот краткий пример: Сначала нам нужно включить зависимость Если мы используем gradle, он будет в файле build.gradle.

    implementation ('org.springframework.boot:spring-boot-starter-aop')

Включите аналог в maven.xml, если используется maven. Напишем класс с методами для тестирования

@Component
public class ClassWithMethods {

    // method under consideration
    public void setA() {
    }

    public void setB() {
    }

}

Посмотрите, мы не будем менять этот класс для подсчета вызовов методов. Затем пишем аспект

@Aspect
@Component // this aspect will be a spring bean
public class AspectForCountingMethodCalls {

    public static AtomicLong setACounter = new AtomicLong(0L);
    public static AtomicLong setBCounter = new AtomicLong(0L);

    @Before("execution (* setA(..))") // executed before every call setA
    public void countSetACall() {
        setACounter.getAndIncrement(); // increase counter
    }

    @Before("execution (* setB(..))") // executed before every call setB
    public void countSetBCall() {
        setBCounter.getAndIncrement(); // increase counter
    }

}

И теперь мы можем это протестировать и насладиться

@SpringBootTest
public class AspectTest {

    @Autowired
    ClassWithMethods classWithMethods;

    @Test
    void testCounter() {
        // call setA 17 times
        for (int i = 0; i < 17; i++) {
            classWithMethods.setA();
        }
        // call setB 3 times
        for (int i = 0; i < 3; i++) {
            classWithMethods.setB();
        }
        // verify that our aspect works
        assertEquals(17L, AspectForCountingMethodCalls.setACounter.get());
        assertEquals(3L, AspectForCountingMethodCalls.setBCounter.get());
    }
}

Мы можем сделать гораздо больше с аспектами, но это выходит за рамки этого ответа.

Это может быть хорошей идеей, я могу использовать AOP и запускать потоки E2E... Спасибо.

AsfK 02.06.2024 13:56

Другие вопросы по теме