Spring Batch @Primary注释覆盖了错误的bean

时间:2017-03-09 10:50:59

标签: java spring spring-boot spring-batch

我跟着this tutorial在Java中配置Spring Batch作业。它通过使用随后由每个数据源实现的接口来提供多个数据源。

这是我到目前为止所做的:

InfrastructureConfig.java

public interface InfrastructureConfiguration {
    @Bean
    DataSource dataSource();
}

MySQLConfig.java

@Configuration
@Primary
public class MySQLConfiguration implements InfrastructureConfiguration {

    @Bean
    public DataSource dataSource() {
        final DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/employees?useSSL=false");
        dataSource.setUsername("testing");
        dataSource.setPassword("testing");
        return dataSource;
    }
}

PostgreSQLConfig.java

@Configuration
public class PostgreSQLConfiguration implements InfrastructureConfiguration {

    @Bean
    public DataSource dataSource() {
        final DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("org.postgresql.Driver");
        dataSource.setUrl("jdbc:postgresql://localhost:5432/postgres");
        dataSource.setUsername("postgres");
        dataSource.setPassword("testing");
        return dataSource;
    }
}

JobConfig.java

@Configuration
public class JobConfig {

    @Autowired
    private InfrastructureConfig infrastructureConfig

    ....
}

通过对我的MySQLConfig使用@Primary注释,我希望使用mySQLConfig bean。相反,我得到了这个:

2017-03-09 12:46:21.422  INFO 1496 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'dataSource' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=mySQLConfiguration; factoryMethodName=dataSource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [config/MySQLConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=postgreSQLConfiguration; factoryMethodName=dataSource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [config/PostgreSQLConfiguration.class]]

它使用postgreSQLConfig bean覆盖mySQLConfig bean,因此使用postgresql驱动程序。问题是,为什么?

3 个答案:

答案 0 :(得分:1)

@Primary放在方法上(@Bean旁边),而不是在班级上。

答案 1 :(得分:0)

尝试使用@Qualifier(name = "")然后明确选择您想要的实例。

您在接口方法上有@Bean注释也很奇怪。 对我来说使用autowire @Configuration类看起来也不好看。它们是用于实例化bean的基于java的配置。

答案 2 :(得分:0)

您可以尝试使用@Profiles注释。

@Profile("mySql")注释mySql配置类,用@Profile("myPostgresql")注释Postgres配置

然后用JobConfig注释@ActiveProfiles("mySql")配置。这样JobConfig应该忽略postgres配置。

假设您在测试中使用MySQL,则可以用@ActiveProfiles("mySql")注释测试类

Spring Profiles documentation

文档中的示例:

@Configuration
public class AppConfig {

  @Bean("dataSource")
  @Profile("development") 
  public DataSource standaloneDataSource() {
    return new EmbeddedDatabaseBuilder()
        .setType(EmbeddedDatabaseType.HSQL)
        .addScript("classpath:com/bank/config/sql/schema.sql")
        .addScript("classpath:com/bank/config/sql/test-data.sql")
        .build();
  }

  @Bean("dataSource")
  @Profile("production") 
  public DataSource jndiDataSource() throws Exception {
    Context ctx = new InitialContext();
    return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
  }
}