通过@Value注释在类和bean之间的区别

时间:2016-06-30 13:50:23

标签: java spring spring-batch spring-annotations

最近,我尝试将带有@Value注释的预定义值添加到Bean:

@Component
public class TaskletConfig {

  @Bean(name = "FilenameExecutionTasklet")
  @JobScope
  public Tasklet FilenameExecutionTasklet() {
      return new Tasklet() {

          @Value("#{jobParameters['inputFilename']}") 
          private String inputFilename;

          @Value("${platformImport.jobParameter.inputFile}") 
          private String inputFile;

          public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

              chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put(inputFile , inputFilename);
              return RepeatStatus.FINISHED;
        }

    };
  }
}

以NullPointerException结束。如果我(在一个Tasklet中)(几乎)相同,它可以工作:

@JobScope
@Component
public class FilenameExecutionTasklet implements Tasklet {

  @Value("${platformImport.jobParameter.inputFile}")
  private String inputFile;

  @Value("#{jobParameters['inputFilename']}") 
  private String inputFilename;

  @Override
  public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
      chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put(inputFile, inputFilename);
      return RepeatStatus.FINISHED;
  }
}

有人可以告诉我为什么吗?我希望两者都有效。

@Value("${platformImport.jobParameter.inputFile}")的值在application.yml。

NPE被chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put(inputFile , inputFilename); inputFile投入。

1 个答案:

答案 0 :(得分:1)

我相信你正在击中NPE因为Spring Batch中的后期绑定和评估顺序。因为FilenameExecutionTasklet能够在JobScope中,所以它允许Spring Batch在评估@Value注释之前评估应用程序上下文中的其他bean(单例范围内的那些bean)。

我对此并不乐观,但您可以将@JobScope添加到TaskletConfig,或者将@Value注释移到您的bean创建方法的争论中

@Component
public class TaskletConfig {

  @Bean(name = "FilenameExecutionTasklet")
  @JobScope
  public Tasklet FilenameExecutionTasklet(
         @Value("#{jobParameters['inputFilename']}") String inputFilename,
         @Value("${platformImport.jobParameter.inputFile} String inputFile ) {

      return new Tasklet() {
          public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
              chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put(inputFile , inputFilename);
              return RepeatStatus.FINISHED;
        }

    };
  }

}

除此之外,我还不太确定你的用例是什么。如果文件名是作为作业参数提供的,那么将它放在执行上下文中是什么意思?

事实上,Tasklet已经可以通过ChunkContext

访问它
public RepeatStatus execute(final StepContribution Contribution, final ChunkContext chunkContext) throws Exception {
    String fileName;
    //one way
    fileName = chunkContext.getStepContext().getStepExecution().getJobExecution().getJobParameters().getString("inputFileName");
    //another way
    fileName = (String) chunkContext.getStepContext().getJobParameters().get("inputFileName");
    return null;
}