我尝试对我的 Spring(使用 Maven)项目的一些方法进行基准测试。我需要在项目中的几个字段上使用@Autowired 和@Inject。当我运行我的项目时,它运行良好。但 JMH 总是通过 @Autowired/@Inject 字段获得 NullPointerException。
public class Resources {
private List<Migratable> resources;
@Autowired
public void setResources(List<Migratable> migratables) {
this.resources = migratables;
}
public Collection<Migratable> getResources() {
return resources;
}
}
我的基准类
@State(Scope.Thread)
public class MyBenchmark {
@State(Scope.Thread)
public static class BenchmarkState {
Resources res;
@Setup
public void prepare() {
res = new Resources();
}
}
@Benchmark
public void testBenchmark(BenchmarkState state, Blackhole blackhole) {
blackhole.consume(state.res.getResources());
}
}
当我运行基准测试时,它在 Resources.getResources()
处收到 NullPointerException
更具体地说,请参阅资源
。
它不能 Autowiring setResources()。但如果我运行我的项目(不包括基准测试),它工作得很好。
如何在基准测试时使用 Autowired 字段消除此 NullPointerException?
最佳答案
以下是如何运行基于 Spring 的基准测试的示例:https://github.com/stsypanov/spring-boot-benchmark .
基本上,您需要将对应用程序上下文的引用存储为基准类的字段,在 @Setup
方法中初始化上下文并在 @TearDown
中关闭它。像这样的事情:
@State(Scope.Thread)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@BenchmarkMode(value = Mode.AverageTime)
public class ProjectionVsDtoBenchmark {
private ManyFieldsRepository repository;
private ConfigurableApplicationContext context;
@Setup
public void init() {
context = SpringApplication.run(Application.class);
context.registerShutdownHook();
repository = context.getBean(ManyFieldsRepository.class);
}
@TearDown
public void closeContext(){
context.close();
}
}
您要测量的逻辑必须封装在从 @Benchmark
注解的方法调用的 Spring 组件的方法中。请记住基准测试的一般规则,以确保您的测量结果正确,例如使用 Blackhole
或从方法返回值来阻止编译器进行 DCE。
关于spring - JMH Benchmark 在 Spring(使用 maven)项目中使用 Autowired 字段获取 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43778671/