Job/Step/Reader/Writer 应该都是bean吧?

Should Job/Step/Reader/Writer all be bean?

就 Spring 批处理参考文档中的所有示例而言,我看到像 job/step/reader/writer 这样的对象都被标记为 @bean,如下所示:

@Bean
public Job footballJob() {
    return this.jobBuilderFactory.get("footballJob")
                     .listener(sampleListener())
                     ...
                     .build();
}

@Bean
public Step sampleStep(PlatformTransactionManager transactionManager) {
    return this.stepBuilderFactory.get("sampleStep")
                .transactionManager(transactionManager)
                .<String, String>chunk(10)
                .reader(itemReader())
                .writer(itemWriter())
                .build();
}

我有一个场景,即服务器端将同时接收请求和 运行 作业(不同的作业名称或具有不同作业参数的相同作业名称)。用法是在并发线程中new一个job对象(包括steps/reader/writers),所以我一般不会把job方法写成@bean,每次new一个job。

而reader在如何将参数传递给对象上实际上是有区别的。如果使用 @bean ,参数必须放在例如使用@StepScope 将 JobParameters 后期绑定到对象中,如下例所示:

@StepScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value(
"#{jobParameters['input.file.name']}") String name) {
return new FlatFileItemReaderBuilder<Foo>()
.name("flatFileItemReader")
.resource(new FileSystemResource(name))
}

如果不使用@bean,我可以直接传参,不需要往JobParameter里放数据,如下

public FlatFileItemReader flatFileItemReader(String name) {
return new FlatFileItemReaderBuilder<Foo>()
.name("flatFileItemReader")
.resource(new FileSystemResource(name))
}

简单的测试表明没有@bean 起作用。但我想正式确认一下:

1、在job/step/reader/writer处使用@bean是不是必须的?

2、如果不是必须的,当我像reader这样new一个对象的时候,需要手动调用afterPropertiesSet()吗?

谢谢!

1、 Is using @bean at job/step/reader/writer mandatory or not ?

不,将批处理工件声明为 beans 不是强制性的。但是您至少希望将 Job 声明为一个 bean,以便从 Spring 的依赖注入中获益(例如将作业存储库引用注入作业等)并能够执行以下操作:

ApplicationContext context = new AnnotationConfigApplicationContext(MyJobConfig.class);
Job job = context.getBean(Job.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
jobLauncher.run(job, new JobParameters());

2、 if it is not mandatory, when I new a object like reader, do I need to call afterPropertiesSet() manually?

我猜想“当我新建一个像 reader 这样的对象时”是指手动创建一个新实例。在这种情况下是的,如果对象不是由 Spring 管理的,则需要自己调用该方法。如果对象声明为 bean,Spring 将调用 afterPropertiesSet() 方法自动。这是一个快速示例:

import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TestAfterPropertiesSet {

    @Bean
    public MyBean myBean() {
        return new MyBean();
    }

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(TestAfterPropertiesSet.class);
        MyBean myBean = context.getBean(MyBean.class);
        myBean.sayHello();
    }

    static class MyBean implements InitializingBean {
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("MyBean.afterPropertiesSet");
        }

        public void sayHello() {
            System.out.println("Hello");
        }
    }

}

这会打印:

MyBean.afterPropertiesSet
Hello