据我所知,spring提供了一些方法将bean注入非托管类。 它可以使用AutowireCapableBeanFactory显式完成。 (How to inject dependencies into a self-instantiated object in Spring?)
但是当弹簧自动执行这样的注射时,我遇到了奇怪的(恕我直言)行为。
这是一个弹簧批的例子,
配置:
@SpringBootConfiguration
public class ProcessorJobConfig {
//.....
@Bean(name = "pullRestTemplate")
public RestTemplate createPullRestTemplate() {
RestTemplate restTemplate = restTemplateBuilder.build();
return restTemplate;
}
@Bean(name = "step")
public Step step(@Autowired ItemReader<Measurement> itemReader,
@Autowired ItemProcessor<Measurement, Event> itemProcessor,
@Autowired ItemWriter<Event> itemWriter) {
return stepBuilderFactory.get("step")
.<Measurement, Event>chunk(Integer.MAX_VALUE)
.reader(itemReader)
.processor(itemProcessor)
.writer(itemWriter)
.build();
}
@Bean(name = "restProcessorJob")
public Job job(@Qualifier("step") Step step) throws Exception {
return jobBuilderFactory.get("restProcessorJob")
.start(step)
.build();
}
@Bean
public ItemReader<Measurement> itemReader() {
RestMeasureReader restMeasureReader = new RestMeasureReader(); // Use new() explicitly
return restMeasureReader;
}
//.....
}
阅读器:
public class RestMeasureReader implements ItemReader<Measurement> {
private static final Logger LOGGER = LoggerFactory.getLogger(RestMeasureReader.class);
/**
* NOTE: This field will be injected automatically by spring, even we are using new() to create instance of this class.
*/
@Autowired
@Qualifier("pullRestTemplate")
private RestTemplate restTemplate;
@Override
public Measurement read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
// do some stuff
}
}
申请本身
@EnableBatchProcessing
@EnableTask
@SpringBootApplication
public class TestAutowiredTaskApplication {
public static void main(String[] args) {
SpringApplication.run(TestAutowiredTaskApplication.class, args);
}
}
即使我使用显式new()来实例化RestMeasureReader,它的RestTemplate字段也将在之后注入。 这是正常的行为吗?我不希望spring在使用new()创建对象时自动注入字段。
答案 0 :(得分:3)
如果您正在讨论在new
课程中使用@Configuration
,那么这是正常行为。这是你的Spring java配置。所以这是Spring管理的上下文。您不会明确地在代码中调用itemReader()
。
所以,当你要这样做时:
@Autowired
private ItemReader<Measurement> iterReader;
您将从Spring的IoC获得RestMeasureReader
的实例。
但是如果您尝试在代码中明确调用new RestMesureReader()
,您将获得RestMesureReader
的新实例,而不是注入@Autowired
字段的Spring代理。
尝试从@Bean
方法声明中删除itemReader()
,并且无法使用RestMesureReader
自动加载。
所以基本上@Configuration
类只是一个Spring配置,而不是真正的java代码。即使你打电话给new
,Spring仍然会给你一个代理类。
有关详细信息,请查看this guide。
答案 1 :(得分:1)
Spring处理由@Bean
注释的方法返回的bean
这允许您在使用Java配置时使用自动装配或实时循环回调。
一个更简约的例子:
@Configuration
public class MyConfiguration {
@Bean
public A a() {
return new A();
}
static class A {
@Autowired
private B b;
@PostConstruct
public void onPostConstruct() {
System.out.println("postConstruct: " + b);
}
}
@Component
static class B {
}
}
这里,即使手动创建名为a
的bean,Spring也会注入依赖项(b
)并调用@PostConstruct
回调。