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;
}