我有一个如下定义的语言翻译界面。
public interface TranslationService {
public TranslationResult translate(TranslationRequeset req);
public int maxTranslatableCount();
}
并且有几种使用谷歌,必应......等的接口实现如下:
public class BingTranslationServiceImpl implements TranslationService {
public TranslationResult translate(TranslationRequeset req){}
public int maxTranslatableCount(){return 10000;}
}
public class GoogleTranslationServiceImpl implements TranslationService {
public TranslationResult translate(TranslationRequeset req){}
public int maxTranslatableCount(){return 2000;}
}
public class FooTranslationServiceImpl implements TranslationService {
public TranslationResult translate(TranslationRequeset req){}
public int maxTranslatableCount(){return 50000;}
}
然后在我们的客户端代码中,如果特定翻译服务失败,我们必须执行故障转移。
为了实现这一点,我引入了一个“TranslationProxy”,在列表中定义故障转移策略,如下所示:
基本上,如果特定服务无法翻译,则会遍历列表。
public class TranslationProxy implements TranslationService {
private List<TranslationService> services;
TranslationResult translate(TranslationRequeset req) {
//
}
public List<TranslationBusinessLogic> getServices() {
return services;
}
public void setServices(List<TranslationBusinessLogic> services) {
this.services = services;
}
}
然后在我的 Spring 配置中,我定义了服务实现如下:
<bean id="bing" class="com.mycompany.prj.BingTranslationServiceImpl" scope="singleton"/>
<bean id="google" class="com.mycompany.prj.GoogleTranslationServiceImpl" scope="singleton"/>
<bean id="foo" class="com.mycompany.prj.FooTranslationServiceImpl" scope="singleton"/>
对于每个故障转移策略,我将“TranslationProxy”bean 定义如下:
<bean id="translationProxy_Bing_Google" class="com.mycompany.prj.TranslationProxy" scope="singleton">
<property name="services">
<list>
<ref bean="bing"/>
<ref bean="google"/>
</list>
</property>
</bean>
<bean id="translationProxy_Foo_Bing_Google" class="com.mycompany.prj.TranslationProxy" scope="singleton">
<property name="services">
<list>
<ref bean="foo"/>
<ref bean="bing"/>
<ref bean="google"/>
</list>
</property>
</bean>
在客户端代码中:
class SomeBusinessLogic {
@Autowired
@Qualified("translationProxy_Bing_Google")
private TranslationService translationService;
public void some_method_which_uses_translation() {
result = translationService(request);
}
}
另一个地方 :
class SomeAnotherBusinessLogic {
@Autowired
@Qualified("translationProxy_Foo_Bing_Google")
private TranslationService translationService;
public void some_method_which_uses_translation_with_different_failover_stradegy() {
result = translationService(request);
}
}
这不是实现这种故障转移策略的最干净的方法吗?
我被要求将故障转移策略移到客户端代码中。
类似以下的东西(这在春天是不可能的):
class SomeBusinessLogic {
@Autowired
@SomeAnnotationDefiningTheStradegy("bing","google")
private TranslationService translationService;
public void some_method_which_uses_translation() {
result = translationService(request);
}
这里的“SomeAnnotationDefiningTheStradegy”是一个注释,它将用参数中定义的 bean 填充列表。