【问题标题】:JMH Benchmark get NullPointerException with Autowired field in Spring(with maven) projectJMH Benchmark 在 Spring(使用 maven)项目中使用 Autowired 字段获取 NullPointerException
【发布时间】:2017-10-02 09:13:50
【问题描述】:

我尝试对我的 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 更具体地说,resources
它不能自动装配 setResources()。但是如果我运行我的项目(不包括基准测试),它工作正常。
如何在基准测试时摆脱带有 Autowired 字段的 NullPointerException?

【问题讨论】:

  • 您找到解决方案了吗?

标签: spring maven benchmarking microbenchmark jmh


【解决方案1】:

以下是如何运行基于 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。

【讨论】:

    【解决方案2】:

    尝试使用

    @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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-10
      • 1970-01-01
      • 1970-01-01
      • 2013-09-02
      • 2016-11-14
      • 2014-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多