我具有如下定义的语言翻译界面。

public interface TranslationService {
  public TranslationResult translate(TranslationRequeset req);
  public int maxTranslatableCount();
}


并使用Google,Bing ... etc对该接口进行了多种实现,如下所示:

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”,它在List中定义了故障转移策略,如下所示:

基本上,如果特定服务翻译失败,则会遍历列表。

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填充列表。

最佳答案

首先,建议您制作一个包含所有翻译服务(enum TranslationServiceProvider {BING, GOOGLE, FOO})的枚举,并使用它代替字符串。将方法添加到TranslationService接口返回提供程序(TranslationServiceProvider getProvider())也会很有用。

我认为,最直接的选择是:

class SomeAnotherBusinessLogic {

    private TranslationService translationService;

    @Autowired
    public void setTranslationService(TranslationDecider translationDecider) {
        translationService = translationDecider.getProxyFor(
            TranslationServiceProvider.BING, TranslationServiceProvider.FOO);
    }

    ...
}

@Component
public class TranslationDeciderImpl implements TranslationDecider {

    @Autowired
    private List<TranslationService> translationServices;

    public TranslationProxy getProxyFor(TranslationServiceProvider ... providers) {
        List<TranslationService> services = // translationServices filtered using getProvider()
        return new TranslationProxy(services);
    }

}


TranslationProxy不是由Spring管理的,但可能不是必需的。如果是,则需要TranslationProxyFactory

10-08 03:26