防止 Spring 容器对提供的 Bean 执行注入

Posted

技术标签:

【中文标题】防止 Spring 容器对提供的 Bean 执行注入【英文标题】:Prevent Spring container from performing injection on provided Bean 【发布时间】:2017-09-22 17:08:58 【问题描述】:

我的目标是将 Spring Batch 与 DataSource 的不同实例分别用于我的 ItemWriterJobRepository,这应该可以工作 like this。

不幸的是,Spring 容器会在稍后阶段注入主数据源,我可以通过调试器确认这一点。这是我的配置:

@RunWith(SpringJUnit4ClassRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@SpringBootTest(classes =  BatchTest.DatabaseConfig.class, BatchTest.BatchTestConfig.class )
public class BatchTest 

    @Configuration
    static class DatabaseConfig 

        @Bean
        @Primary
        @ConfigurationProperties("spring.datasource")
        public DataSource primaryDataSource() 
            return DataSourceBuilder.create()
                    .build();
        

        @Bean
        @ConfigurationProperties("spring.secondaryDatasource")
        public DataSource secondaryDataSource() 
            return DataSourceBuilder.create()
                    .build();
        
    

    @Configuration
    @EnableBatchProcessing
    static class BatchTestConfig 

        @Bean()
        BatchConfigurer configurer(@Qualifier("secondaryDataSource") DataSource dataSource) 
            return new DefaultBatchConfigurer(dataSource);
        
    

我认为这是由于

中定义的setter-injection
package org.springframework.batch.core.configuration.annotation;

@Component
public class DefaultBatchConfigurer implements BatchConfigurer 

    @Autowired(required = false)
    public void setDataSource(DataSource dataSource) 
        this.dataSource = dataSource;
        this.transactionManager = new DataSourceTransactionManager(dataSource);
    

所以现在我想知道上面提到的 SO 响应如何工作,或者在我的情况下不起作用。我可以以某种方式禁用提供的 bean 上的额外设置器注入吗?

【问题讨论】:

您可以将@Primary 注释添加到@Bean BatchConfigurer configurer(...) 定义在BatchTestConfig 感谢您的建议,不幸的是它产生了相同的结果,即使用辅助数据源创建 bean 并稍后注入主数据源。 然后尝试覆盖DefaultBatchConfigurer#setDataSource 并添加限定符。我还要说,使用这种配置,您可能有两个 DefaultBatchConfigurer 类型的 bean。一个由您的配置决定,另一个由@Component 决定,但前提是组件扫描配置了此包 谢谢你,虽然感觉很奇怪,但这很有效。随时发布它作为我接受的答案。关于两个 bean,我确信它只是一个 bean,因为我可以通过调试器确认 setter-injection 会覆盖之前指定的 DataSource setter注入方法是否只调用一次? 【参考方案1】:

T尝试覆盖DefaultBatchConfigurer#setDataSource并将限定符添加到setDataSource方法:

    @Bean()
    BatchConfigurer configurer(@Qualifier("secondaryDataSource") DataSource dataSource) 
        return new DefaultBatchConfigurer(dataSource) 

            @Autowired(required = false)
            public void setDataSource(@Qualifier("secondaryDataSource") DataSource dataSource) 
                super.setDataSource(dataSource);
            
        ;
    

我同意这有点奇怪,但春季批次有这样的限制也很奇怪。

您甚至可以尝试在没有任何注释的情况下进行覆盖。我不记得 Spring 是否也在类层次结构中搜索注释。

【讨论】:

以上是关于防止 Spring 容器对提供的 Bean 执行注入的主要内容,如果未能解决你的问题,请参考以下文章

Spring学习IOC容器配置bean:定义与实例化

20191225 Spring官方文档(Core 1.6-1.8)

Spring基础14——Bean的生命周期

Spring入门第十一课

Spring Bean后处理器

Spring之核心容器bean