如何在运行时基于Spring而不使用XML的属性注入不同的服务

我正在使用Spring Boot for Java独立应用程序。 我有一个使用服务的bean。 我想在运行时注入该服务的不同实现,基于Spring属性文件中的属性(就此而言为4)。


这听起来像工厂模式,但Spring也允许使用注释来解决问题,就像这样。

@Autowired @Qualifier("selectorProperty") private MyService myService; 

然后在beans.xml文件中我有一个别名,这样我就可以在@Qualifier中使用该属性。

  

在我的不同实现中,我会有不同的限定符。

 @Component("Selector1") public class MyServiceImpl1 @Component("Selector2") public class MyServiceImpl2 

application.properties

 selector.property = Selector1 selector.property = Selector2 

而对于工厂模式,在Spring中,您可以使用ServiceLocatorFactoryBean来创建一个可以提供相同function的工厂。

     public interface MyServiceFactory { MyService getMyService(String selector); } 

然后在你的bean中你可以使用类似的东西在运行时获得正确的实现,具体取决于属性的值。

 @Value("${selector.property}") private String selectorProperty; @Autowired private MyServiceFactory myServiceFactory; private MyService myService; @PostConstruct public void postConstruct() { this.myService = myServiceFactory.getMyService(selectorProperty); } 

但是这个解决方案的问题是我找不到一种方法来避免使用XML来定义工厂,我只想使用注释。


所以问题是,是否有一种方法可以仅使用注释来使用ServiceLocatorFactoryBean(或类似的东西),或者如果我不想在XML中定义bean,我是否被迫使用@Autowired @Qualifier方法? 或者有没有其他方法可以在运行时根据Spring 4避免XML的属性注入不同的服务? 如果您的答案只是使用带有别名的@Autowired @Qualifier ,请说明为什么这比使用众所周知的工厂模式更好。

使用额外的XML迫使我在我的Launcher类中使用@ImportResource("classpath:beans.xml") ,我也不想使用它。

谢谢。

实际上,您可以在没有XML的情况下使用ServiceLocatorFactory,方法是将其声明为配置文件中的bean。

 @Bean public ServiceLocatorFactoryBean myFactoryServiceLocatorFactoryBean() { ServiceLocatorFactoryBean bean = new ServiceLocatorFactoryBean(); bean.setServiceLocatorInterface(MyServiceFactory.class); return bean; } @Bean public MyServiceFactory myServiceFactory() { return (MyServiceFactory) myFactoryServiceLocatorFactoryBean().getObject(); } 

然后你仍然可以照常使用工厂,但不涉及XML。

 @Value("${selector.property}") private String selectorProperty; @Autowired @Qualifier("myServiceFactory") private MyServiceFactory myServiceFactory; private MyService myService; @PostConstruct public void postConstruct() { this.myService = myServiceFactory.getMyService(selectorProperty); } 

我正在使用Spring配置文件

例如,使用dataSources使用它,您可以根据需要定义任意数量的dataSource

 @Configuration @Profile("dev") public class StandaloneDataConfig { @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(); } } @Configuration @Profile("cloud") public class CloudDataConfig { @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(); } } 

并在运行时,通过指定

-Dspring.profiles.active = “我的资料”

您激活了一个或另一个配置(所有这些配置必须在主配置中导入,它们将根据活动配置文件被忽略)。

这是一篇很好的文章: http : //spring.io/blog/2011/02/14/spring-3-1-m1-introducing-profile/