Spring Sourceは、バージョン1.1.4でServiceLocatorFactoryBeanを作成したときに、問題を参照していました。これを使用するには、以下のようなインターフェースを追加する必要があります。
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修飾子に基づいて目的のサービスを返します。Springアノテーションを除けば、コードはSpringに依存していません。上記に対して以下の単体テストを実行しました
@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();
}
}
コンソールに
Hello、A Service
Hello、 BServiceが表示されます
警告の言葉。APIドキュメントには、
「このようなサービスロケーターは、通常、プロトタイプBeanに使用されます。つまり、呼び出しごとに新しいインスタンスを返すことになっているファクトリメソッドに使用されます。シングルトンBeanの場合、ターゲットBeanの直接セッターまたはコンストラクターインジェクションが推奨されます。 」</p>
なぜこれが問題になるのか理解できません。私のコードでは、serviceThatNeedsServiceInterface.useService();への2つのシーケンス呼び出しで同じサービスを返します。
私の例のソースコードはGitHubにあります