Spring Java 基于配置 "chicken and Egg situation"

Spring Java based config "chicken and Egg situation"

最近才开始研究 Spring,特别是它的最新功能,例如 Java 配置等。 我有这个有点奇怪的问题:

Java 配置片段:

@Configuration
@ImportResource({"classpath*:application-context.xml","classpath:ApplicationContext_Output.xml"})
@Import(SpringJavaConfig.class)
@ComponentScan(excludeFilters={@ComponentScan.Filter(org.springframework.stereotype.Controller.class)},basePackages = " com.xx.xx.x2.beans")
public  class ApplicationContextConfig extends WebMvcConfigurationSupport {
    private static final Log log = LogFactory.getLog(ApplicationContextConfig.class);

    @Autowired
    private Environment env;

    @Autowired
    private IExtendedDataSourceConfig dsconfig;    

    @PostConstruct
    public void initApp() {
     ...

    }   

    @Bean(name="transactionManagerOracle")
    @Lazy
    public DataSourceTransactionManager transactionManagerOracle() {
        return new DataSourceTransactionManager(dsconfig.oracleDataSource());
    }

IExtendedDataSourceConfig 有两个实现,它们基于 spring 活动配置文件中的一个或另一个实例化。对于这个例子,假设这是实现:

@Configuration
@PropertySources(value = {
        @PropertySource("classpath:MYUI.properties")})
@Profile("dev")
public class MYDataSourceConfig implements IExtendedDataSourceConfig {
    private static final Log log = LogFactory.getLog(MYDataSourceConfig.class);

    @Resource
    @Autowired
    private Environment env;

    public MYDataSourceConfig() {
        log.info("creating dev datasource");
    }

    @Bean
    public DataSource oracleDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
        dataSource.setUrl(env.getProperty("oracle.url"));
        dataSource.setUsername(env.getProperty("oracle.user"));
        dataSource.setPassword(env.getProperty("oracle.pass"));
        return dataSource;
    }

问题是当调用 transactionManagerOracle bean 时,(即使我尝试将其标记为惰性)dsconfig 变量值似乎为空。

我想先处理 @beans,然后再处理所有 Autowire,有解决办法吗?我如何告诉 spring 在创建 bean 之前注入 dsconfig 变量,或者在注入 dsconfig 之后以某种方式创建 @beans

您可以只将 DataSource 指定为事务管理器 bean 的方法参数。 Spring 然后将自动注入在活动配置文件中配置的数据源:

@Bean(name="transactionManagerOracle")
@Lazy
public DataSourceTransactionManager transactionManagerOracle(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

如果您仍想通过配置 class 执行此操作,请将其指定为参数:

public DataSourceTransactionManager transactionManagerOracle(IExtendedDataSourceConfig dsconfig) {}

在这两种方式中,您都声明了对另一个 bean 的直接依赖,Spring 将确保依赖的 bean 存在并将被注入。