Spring Заполнитель компонентов и свойств

Кто-нибудь знает, смогу ли я использовать заполнитель свойств в качестве выражения в квалификаторе? Кажется, я не могу работать.

Я использую spring 3.0.4.

@Controller
public class MyController {
   @Autowired
   @Qualifier("${service.class}")
   Service service;
}

@Service
@Qualifier("ServiceA")
ServiceA implements Service {
   public void print() {
       System.out.println("printing ServiceA.print()");
   } 
}

@Service
@Qualifier("ServiceB")
ServiceB implements Service {
   public void print() {
      System.out.println("printing ServiceB.print()");
   } 
}

XML:

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="file:/etc/config.properties"/>
</bean>

config.properties:

config.properties
service.class=serviceB

Ответ 1

Это работает. Вы можете оставить имена служб, если используете только имя spring bean по умолчанию. serviceA vs ServiceA и т.д.

@Controller
class MyController {
@Autowired(required=false)
@Qualifier("Service")
Service service;

public static void main(String[] args) {
   ApplicationContext context = new ClassPathXmlApplicationContext("app-ctx.xml", MyController.class);
   for(String s:context.getBeanDefinitionNames()){
       System.out.println(s);
       for(String t:context.getAliases(s)){
           System.out.println("\t" + t);
       }
   }
   context.getBean(MyController.class).service.print();
  }
}

public interface Service {
    void print();
}

@Service(value="ServiceA")
public class ServiceA implements example.Service {
    public void print() {
        System.out.println("printing ServiceA.print()");
    } 
}

@Service(value="ServiceB")
public class ServiceB implements example.Service {
    public void print() {
        System.out.println("printing ServiceB.print()");
    } 
}

XML:

<beans>
    <alias name="${service.class}" alias="Service"/>
    <context:property-placeholder location="example/app.properties"/>
    <context:component-scan base-package="example"/>
<beans>

Реквизит:

service.class=ServiceB

Ответ 2

Я бы рискнул догадаться, что ответ - нет, только основываясь на написании писем на нескольких страницах javadoc. Например, см. Документы для @Value:

http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html

Обратите внимание, что они особо упоминают использование выражений в аннотации. Для сравнения, документы для @Qualifier:

http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/beans/factory/annotation/Qualifier.html

Которые не упоминают выражения. Очевидно, что не окончательный ответ (но spring, как правило, очень хорош в документации). Кроме того, если выражения поддерживались в аннотации @Qualifier, я ожидаю, что они будут работать так же, как аннотация @Value (только на основе spring, являющейся очень последовательной структурой).

Spring 3.1 имеет новый профиль bean, который, похоже, может выполнить что-то вроде того, что вы пытаетесь сделать. Здесь напишите для этого:

http://blog.springsource.com/2011/02/14/spring-3-1-m1-introducing-profile/

Ответ 3

Это решение работает без XML и с файлом свойств.

Улучшены ваши классы:

MyController.java:

@Controller
public class MyController {
    @Autowired
    public MyController(@Qualifier("MyServiceAlias") MyService myService) {
        myService.print();
    }
}

ServiceA.java:

@Service("serviceA")
public class ServiceA implements MyService {
    @Override
    public void print() {
        System.out.println("printing ServiceA.print()");
    }
}

ServiceB.java:

@Service("serviceB")
public class ServiceB implements MyService {
    @Override
    public void print() {
        System.out.println("printing ServiceB.print()");
    }
}

application.properties (здесь вы можете изменить, какой класс будет загружен):

service.class=serviceA

И важный файл конфигурации AppConfig.java:

@Configuration
public class AppConfig {

    @Autowired
    private ApplicationContext context;

    @Bean
    public MyService MyServiceAlias(@Value("${service.class}") String qualifier) {
        return (MyService) context.getBean(qualifier);
    }
}

Дополнительные пояснения:

  • Используйте @Qualifier только для поля, которое будет автообновлено. Для сервисов укажите bean имя, используйте @Service.
  • Если вы хотите стандартное имя bean, вам не нужно использовать @Service с именем specyify. Например, стандартное имя bean для ServiceA - serviceA (не serviceA - см. Большую первую букву), поэтому @Service("serviceA") избыточное (@Service достаточно).
  • Я основывал AppConfig на этом ответе: Spring bean Псевдоним в JavaConfig.
  • Это решение лучше, чем этот Spring Заполнитель свойств и свойств, поскольку вам не нужен XML.
  • Протестировано на Spring Загрузка 1.5.7.

Ответ 4

Может быть, это вихрь:

@Controller
public class MyController {

   private String serviceId;

   @Value("${serviceId}")
   public void setServiceId(String serviceId) {
      this.serviceId = serviceId;
   }

   @Autowired
   @Qualifier(serviceId)
   Service service;
}