衡量方法的重用

问题描述 投票:0回答:1

我需要统计特定包下的任何方法被调用了多少次(类似于Hieracy,但在运行时,导出结果)

例如: 方法setA被调用17次,方法setB被调用3次...

基于this答案我成功提取了实现类中的所有方法,但我不知道如何找到生产代码中的所有用途。

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

java spring-boot reflection
1个回答
0
投票

计算方法调用次数的最佳方法是使用方面。请参阅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,则在maven.xml中包含模拟 我们将编写一个带有测试方法的类

@Component
public class ClassWithMethods {

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

    public void setB() {
    }

}

看,我们不会改变这个类来进行方法调用计数。 然后我们写aspect

@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 10 times
        for (int i = 0; i < 10; i++) {
            classWithMethods.setA();
        }
        // call setB 10 times
        for (int i = 0; i < 100; i++) {
            classWithMethods.setB();
        }
        // verify that our aspect works
        assertEquals(10L, AspectForCountingMethodCalls.setACounter.get());
        assertEquals(100L, AspectForCountingMethodCalls.setBCounter.get());
    }
}

我们可以用方面做更多的事情,但这超出了这个答案的范围

© www.soinside.com 2019 - 2024. All rights reserved.