복붙노트

[SPRING] XML없이 Spring을 사용하여 속성을 기반으로 런타임에 여러 서비스를 주입하는 방법

SPRING

XML없이 Spring을 사용하여 속성을 기반으로 런타임에 여러 서비스를 주입하는 방법

Java 독립 실행 형 응용 프로그램 용 Spring Boot를 사용하고 있습니다. 나는 서비스를 이용하는 콩을 가지고있다. 나는 Spring에서 프로퍼티 파일의 프로퍼티를 기반으로 런타임에 해당 서비스의 다른 구현을 삽입하려고한다.

이것은 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 방법을 사용해야합니까? 또는 XML을 피하는 Spring 4의 속성을 기반으로 런타임에 다른 서비스를 주입하는 다른 방법이 있습니까? 당신의 대답이 앨리어스와 함께 @Autowired @Qualifier를 사용하는 것이라면 잘 알려진 공장 패턴을 사용하는 것이 낫다는 이유를 말해주십시오.

여분의 XML을 사용하면 Launcher 클래스에서 @ImportResource ( "classpath : beans.xml")를 사용하게됩니다. 사용하지 않으려합니다.

감사.

해결법

  1. ==============================

    1.사실 XML을 사용하지 않고 ServiceLocatorFactory를 구성 파일의 Bean으로 선언하여 사용할 수 있습니다.

    사실 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);
    }
    
  2. ==============================

    2.스프링 프로파일을 사용하고 있습니다.

    스프링 프로파일을 사용하고 있습니다.

    예 : dataSources 이를 사용하여 원하는만큼 많은 데이터 소스를 정의 할 수 있습니다.

    @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();
        }
    
    }
    

    그리고 런타임에서

    하나 또는 다른 구성을 활성화합니다 (모든 구성은 기본 구성에서 가져와야하며 활성화 된 프로파일을 기준으로 무시됩니다).

    다음은 좋은 기사입니다. http://spring.io/blog/2011/02/14/spring-3-1-m1-introducing-profile/

  3. from https://stackoverflow.com/questions/26463393/how-to-inject-different-services-at-runtime-based-on-a-property-with-spring-with by cc-by-sa and MIT license