小编典典

如何在不带XML的Spring的基础上基于属性在运行时注入不同的服务

spring-boot

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


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

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

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

<alias name="${selector.property}" alias="selectorProperty" />

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

@Component("Selector1")
public class MyServiceImpl1

@Component("Selector2")
public class MyServiceImpl2

application.properties

selector.property = Selector1

selector.property = Selector2

关于工厂模式,在Spring中,您可以使用ServiceLocatorFactoryBean创建可以为您提供相同功能的工厂。

<bean
  class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean"
  id="myServiceFactory">
  <property
    name="serviceLocatorInterface"
    value="my.company.MyServiceFactory">
  </property>
</bean>

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迫使我@ImportResource("classpath:beans.xml")在Launcher类中使用,我不想使用任何一个。

谢谢。


阅读 242

收藏
2020-05-30

共1个答案

小编典典

实际上,您可以通过在配置文件中将其声明为Bean来使用不带XML的ServiceLocatorFactory。

@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);
}
2020-05-30