【问题标题】:Difference between class and bean by @Value annotation通过@Value注解区分class和bean
【发布时间】:2016-06-30 13:50:22
【问题描述】:

最近,我尝试将带有@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 中抛出。

【问题讨论】:

  • 第一个例子中你在哪一行有 NPE?
  • 对不起,忘了告诉:见编辑。

标签: java spring spring-batch spring-annotations


【解决方案1】:

我相信您遇到了 NPE,因为 Spring Batch 中的后期绑定和评估顺序。因为FilenameExecutionTasklet 主管在JobScope 中,所以它允许Spring Batch 在评估@Value 注释之前评估应用程序上下文中的其他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;
}

【讨论】:

  • 嘿!谢谢你的回答。你的第一段听起来很合理。我对春季批次的了解并不深入,无法了解所有这些注释的表面之下是什么。不幸的是,您将@JobScope 注释放在“TaskletConfig”级别的建议是不正确的。但是,我不知道我可以以与ExecutionContext 类似的方式访问 JobParameters。感谢那。 (赞成票的原因。)
  • 有趣的是 @JobScope 放置没有效果。出于好奇,您是否也尝试将@Value 属性作为FilenameExecutionTasklet() 方法的参数?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-13
  • 2019-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-29
相关资源
最近更新 更多