在Spring中使用注释时如何更改实现类?

时间:2015-07-19 16:41:15

标签: spring

我习惯使用Spring进行xml配置。使用xml,我可以为一个类提供一个主要实现和一个测试实现,这样测试实现将用于JUnit测试,如何使用注释执行此操作?因为看起来已经在" @限定符"中选择了实现。注释?

让我们举个例子:

<bean id="myService" class="example.Service" />
<bean id="myHibernateDao" class="example.HibernateDao" />
<bean id="myStubDao" class="example.StubDao" />

在xml配置中,我可以在src / main / resources中使用它:

<bean id="myService" class="example.Service">
  <ref="myHibernateDao" />
</bean>

这在src / test / resources中:

<bean id="myService" class="example.Service">
  <ref="myStubDao" />
</bean>

如果我已将@Qualifier(&#34; myHibernateDao&#34;)声明到我的服务类中,如何使用注释执行此操作?

2 个答案:

答案 0 :(得分:0)

正如上面的评论和spring blog中所述,您可以通过@Profile注释执行此操作。

请从以下示例中找到示例配置

DataConfig.java

interface DataConfig {

    DataSource dataSource();

}

StandaloneDataConfig .java

@Configuration
@Profile("dev")
public class StandaloneDataConfig implements DataConfig {

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

JndiDataConfig.java

@Configuration
@Profile("production")
public class JndiDataConfig implements DataConfig {

    @Bean
    public DataSource dataSource() {
        try {
            Context ctx = new InitialContext();
            return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
        } catch (NamingException ex) {
            throw new RuntimeException(ex);
        }
    }

}

TransferServiceConfig.java

@Configuration
public class TransferServiceConfig {

    @Autowired
    DataConfig dataConfig;

    @Bean
    public TransferService transferService() {
        return new DefaultTransferService(accountRepository(), feePolicy());
    }

    @Bean
    public AccountRepository accountRepository() {
        return new JdbcAccountRepository(dataConfig.dataSource());
    }

    @Bean
    public FeePolicy feePolicy() {
        return new ZeroFeePolicy();
    }

}

将bean配置文件设置为应用程序上下文

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setDefaultProfiles("dev");
ctx.register(TransferServiceConfig.class, StandaloneDataConfig.class,
        JndiDataConfig.class);
ctx.refresh();

由于bean配置文件已设置为DevTransferServiceConfig将注入StandaloneDataConfig

答案 1 :(得分:0)

你基本上可以用@Configuration类做同样的事情。

生产设置

假设您有许多不同的DAO实现可能会或可能不会实现一个通用接口(它并不重要)。让我们进一步假设MyServiceDao是您的Service课程所需的具体实现。

编写以下配置类:

@Configuration
public class MyServiceConfiguration {

    @Bean
    public Service myService(MyServiceDao dao) {
        return new Service(dao);
    }

}

-

@Configuration
public class MyProductionServiceDaoConfiguration {

    @Bean
    public MyServiceDao myServiceDao() {
        return new MyServiceDao();
    }

}

使用@Configuration注释的@Bean类中的方法符合Spring的自动布线要求。在上面的MyServiceConfiguration中,Spring将使用method参数的类型来查找匹配的bean。如果在创建Spring上下文时包含MyProductionServiceDaoConfiguration,则这将是MyServiceDao创建的myServiceDao()的实例。

测试设置

在测试中,您希望将MyServiceDao替换为存根。存根需要扩展MyServiceDao,以便Spring可以根据类型找到正确的bean。让我们调用存根MyServiceDaoStub。无论您是使用像Mockito这样的库(也可以创建存根,而不仅仅是模拟)创建它,或者实际编写MyServiceDao的扩展名都取决于您。

不要在Spring配置中包含MyProductionServiceDaoConfiguration,而是使用以下类:

@Configuration
public class MyTestServiceDaoConfiguration {

    @Bean
    public MyServiceDao myServiceDao() {
        return new MyServiceDaoStub();
    }

}

在测试中使用@ContextConfiguration加载测试设置:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { MyServiceConfiguration.class, MyTestServiceDaoConfiguration.classs })
public class MyServiceTest {

    // your tests

}

使用@Autowired

Spring还将处理从@Autowired带注释的方法返回的对象中的@Bean注释。如果您的Service看起来像这样:

public class Service {

    @Autowired
    private MyServiceDao dao;

    // more code

}

您可以将myService()方法更改为:

@Bean
public Service myService() {
    return new Service();
}