有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在没有XML的情况下,基于Spring的属性在运行时注入不同的服务

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


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

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

然后在豆子里。xml文件我有一个别名,所以我可以使用@Qualifier中的属性

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

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

@Component("Selector1")
public class MyServiceImpl1

@Component("Selector2")
public class MyServiceImpl2

申请。属性

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定义工厂的方法,我只想使用注释


所以问题是,有没有办法只使用注释来使用ServiceLocatoryFactoryBean(或类似的东西),或者如果我不想在XML中定义Bean,我是被迫使用@Autowired@限定符的方式?或者有没有其他方法可以在运行时基于Spring 4的属性注入不同的服务?如果你的答案是只使用@Autowired @Qualifier和别名,请给出一个原因,为什么这比使用众所周知的工厂模式更好

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

谢谢


共 (2) 个答案

  1. # 1 楼答案

    实际上,通过在配置文件中将ServiceLocatorFactory声明为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);
    }
    
  2. # 2 楼答案

    我使用的是Spring配置文件

    例如数据源 使用它,您可以定义任意多个数据源

    @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="myProfile"

    您激活了一个或另一个配置(所有配置都必须导入到主配置中,根据活动配置文件忽略它们)

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