Spring Qualifier и свойство placeholder - PullRequest
23 голосов
/ 18 октября 2011

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

Я использую 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

Ответы [ 4 ]

40 голосов
/ 03 октября 2012

Это работает.Вы можете оставить имена сервисов, если вы просто используете имя бина по умолчанию.serviceA против 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
9 голосов
/ 02 ноября 2017

Это решение работает без 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 только для поля, которое будет автоматически подключено.Для сервисов, чтобы указать имя компонента, используйте @Service.
  • Если вы хотите стандартное имя компонента, вам не нужно использовать @Service с указанным именем.Например, стандартное имя компонента для ServiceA - serviceA (не ServiceA - см. Большую первую букву), поэтому @Service("serviceA") избыточно (достаточно @Service).
  • Я основал AppConfig на этомответ: Псевдоним bean-компонента Spring в JavaConfig .
  • Это решение лучше, чем квалификатор Spring и заполнитель свойства , поскольку вам не нужен XML.
  • Проверено на Spring Boot 1.5.7.
4 голосов
/ 19 октября 2011

Я бы рискнул предположить, что ответ - нет, просто основываясь на рецензиях на нескольких страницах 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/

0 голосов
/ 19 октября 2011

Может быть, это круто:

@Controller
public class MyController {

   private String serviceId;

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

   @Autowired
   @Qualifier(serviceId)
   Service service;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...