[英]JMH Benchmark get NullPointerException with Autowired field in Spring(with maven) project
我嘗試對我的 Spring (with 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()
更具體地說是在resources
獲得 NullPointerException。
它不能自動裝配 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();
}
}
您要測量的邏輯必須封裝在 Spring 組件的一個方法中,該方法從@Benchmark
注釋方法調用。 記住基准測試的一般規則以確保您的測量是正確的,例如使用Blackhole
或從方法返回值來防止編譯器從 DCE。
嘗試使用
測試類上的@RunWith(SpringJUnit4ClassRunner.class) and @ContextConfiguration(locations = {...})
。 這應該初始化Spring TestContext Framework並讓您自動關聯依賴項。
如果這不起作用,則必須使用以下任一方法顯式啟動Spring ApplicationContext作為@Setup帶注釋方法的一部分。
ClassPathXmlApplicationContext,FileSystemXmlApplicationContext或WebXmlApplicationContext並從該上下文解析bean:
ApplicationContext context = new ChosenApplicationContext("path_to_your_context_location");
res = context.getBean(Resources.class);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.