I'm looking at the samples for spring-batch and I'm surprised to see a bean constructor method being called directly rather than through a bean reference. I'm wondering if this is an error.
...
@Configuration
@EnableBatchProcessing
public class SpringBatchConfig {
...
@Bean
public FlatFileItemReader<User> itemReader() {
FlatFileItemReader<User> flatFileItemReader = new FlatFileItemReader<>();
...
flatFileItemReader.setLineMapper(lineMapper());
return flatFileItemReader;
}
@Bean
public LineMapper<User> lineMapper() {
...
}
Whereas the bean constructor method lineMapper()
is annotated as @Bean
, the bean constructor method itemReader()
does not inject the bean in its constructor but rather calls lineMethod()
directly.
I would have expected this definition of itemReader()
:
@Bean
public FlatFileItemReader<User> itemReader(LineMapper<User> lineMapper) {
FlatFileItemReader<User> flatFileItemReader = new FlatFileItemReader<>();
...
flatFileItemReader.setLineMapper(lineMapper);
return flatFileItemReader;
}
Isn't this an error in the current spring-batch samples? Or am I missing something? Perhaps @Configuration
does something magic and converts direct calls to constructors into a bean with a proxy? Perhaps lineMapper()
doesn't need to be a bean at all?
Thanks for any insight.
Both ways you mentioned will have the same effect which will inject the LineMapper
bean into the FlatFileItemReader
's @bean
method.
For the SpringBatchConfig
case , it is using injecting inter-bean dependencies feature, which allow to inject a bean into a @Bean
method via direct method call. And your guess is correct , it works because the @Bean
method is get proxied by the ConfigurationClassEnhancer.BeanMethodInterceptor
if you are interested to know how does it works in code level.
Please note this feature will only enable if you are using full bean mode (i.e. Then @Bean
method is defined inside the @Configuration
class) and @Configuration
's proxyBeanMethods=true
(default value).
Otherwise, any of the following situation will cause calling lineMapper()
just create a new instance but not accessing the LineMapper
instance from the spring context :
@Component
public class SpringBatchConfig {
@Bean
public FlatFileItemReader<User> itemReader() {
FlatFileItemReader<User> flatFileItemReader = new FlatFileItemReader<>();
...
flatFileItemReader.setLineMapper(lineMapper());
return flatFileItemReader;
}
@Bean
public LineMapper<User> lineMapper() {
...
}
}
proxyBeanMethods=false
:@Configuration(proxyBeanMethods = false)
public class SpringBatchConfig {
@Bean
public FlatFileItemReader<User> itemReader() {
FlatFileItemReader<User> flatFileItemReader = new FlatFileItemReader<>();
...
flatFileItemReader.setLineMapper(lineMapper());
return flatFileItemReader;
}
@Bean
public LineMapper<User> lineMapper() {
...
}
}