Источник Spring ссылался на вашу проблему, когда они создали ServiceLocatorFactoryBean еще в версии 1.1.4. Для того, чтобы использовать его необходимо добавить интерфейс, аналогичный приведенному ниже:
public interface ServiceLocator {
//ServiceInterface service name is the one
//set by @Component
public ServiceInterface lookup(String serviceName);
}
Вам нужно добавить следующий фрагмент кода в свой applicationContext.xml
<bean id="serviceLocatorFactoryBean"
class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
<property name="serviceLocatorInterface"
value="org.haim.springframwork.stackoverflow.ServiceLocator" />
</bean>
Теперь ваш ServiceThatNeedsServiceInterface будет выглядеть один ниже:
@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 возвращает желаемую услугу, основанную на классификаторе RequestContext. Помимо весенних аннотаций ваш код не зависит от весны. я выполнил следующий тест блока для вышеприведенного
@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();
}
}
Консоль покажет
Здравствуйте, службу
Здравствуйте, В службе
Слова предупреждения. В документации по API указывается, что
«Такие локаторы сервисов ... обычно будут использоваться для прототипов beans, то есть для заводских методов, которые должны возвращать новый экземпляр для каждого вызова ... Для однотонных bean-компонентов, прямой установщик или инсталляция конструктора целевого компонента предпочтительнее. "
Я не могу понять, почему это может вызвать проблему. В моем коде он возвращает одну и ту же услугу на двух последовательных вызовах serviceThatNeedsServiceInterface.useService();
Можно найти исходный код моего примера в GitHub
Бинго! Это правильный ответ. Я не против, что крошечный бит XML-конфигурации. – Strelok