Spring Source faceva riferimento al tuo problema quando hanno creato il ServiceLocatorFactoryBean nella versione 1.1.4. Per utilizzarlo è necessario aggiungere un'interfaccia simile a quella riportata di seguito:
public interface ServiceLocator {
//ServiceInterface service name is the one
//set by @Component
public ServiceInterface lookup(String serviceName);
}
è necessario aggiungere il seguente frammento al applicationContext.xml
<bean id="serviceLocatorFactoryBean"
class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
<property name="serviceLocatorInterface"
value="org.haim.springframwork.stackoverflow.ServiceLocator" />
</bean>
Ora il vostro ServiceThatNeedsServiceInterface avrà un aspetto simile a quello qui sotto:
@Component
public class ServiceThatNeedsServiceInterface {
// What to do here???
// @Autowired
// ServiceInterface service;
/*
* ServiceLocator lookup returns the desired implementation
* (ProductAService or ProductBService)
*/
@Autowired
private ServiceLocator serviceLocatorFactoryBean;
//Let’s assume we got this from the web request
public RequestContext context;
public void useService() {
ServiceInterface service =
serviceLocatorFactoryBean.lookup(context.getQualifier());
service.someMethod();
}
}
ServiceLocatorFactoryBean tornerà il servizio desiderato in base alla qualificazione RequestContext. Oltre alle annotazioni primaverili, il tuo codice non dipende da Spring. Ho eseguito il seguente test unità per quanto sopra
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:META-INF/spring/applicationContext.xml" })
public class ServiceThatNeedsServiceInterfaceTest {
@Autowired
ServiceThatNeedsServiceInterface serviceThatNeedsServiceInterface;
@Test
public void testUseService() {
//As we are not running from a web container
//so we set the context directly to the service
RequestContext context = new RequestContext();
context.setQualifier("ProductAService");
serviceThatNeedsServiceInterface.context = context;
serviceThatNeedsServiceInterface.useService();
context.setQualifier("ProductBService");
serviceThatNeedsServiceInterface.context = context;
serviceThatNeedsServiceInterface.useService();
}
}
La console visualizzerà
Ciao, un servizio di
Ciao, B Servizio
Una parola di avvertimento. La documentazione dell'API afferma che
"Tali locatori di servizio ... saranno tipicamente usati per i bean prototipo, cioè per i metodi di produzione che dovrebbero restituire una nuova istanza per ogni chiamata ... Per i bean singleton, il setter diretto o l'iniezione del costruttore del bean di destinazione è preferibile. "
Non riesco a capire perché questo potrebbe causare un problema. Nel mio codice restituisce lo stesso servizio su due sequenze di chiamate a serviceThatNeedsServiceInterface.useService();
È possibile trovare il codice sorgente per il mio esempio in GitHub
Bingo! Questa è la risposta corretta. Non mi interessa quel pezzettino di configurazione XML. – Strelok