0

我有一个实用程序/常量类,其中包含一个Map<String, Authorizer>带有Authorizer几个不同实现的接口。我使用跨不同流的映射来获取包含一些String(授权方法的名称)的对象,然后映射到特定Authorizer的 ,然后完成一些授权。

我正在使用 Guice 来连接Authorizer类,但这种方法使我无法使实用程序类(包含Map)成为具有空私有构造函数的真正实用程序类。我有一个看起来很时髦的解决方法,让 Guice 和 Checkstyle 都满意,但我想知道是否有更好的方法。

我的实用程序类:

public final class Constants {
  @Inject
  private Constants() {}

  public static final String AUTH_METHOD_ONE = "Auth1";
  public static final String AUTH_METHOD_TWO = "Auth2";

  @Singleton
  @Inject
  @Getter // For Checkstyle, as AUTH_METHODS isn't a true static final constant
  private static Map<String, Authorizer> authMethods;
}

我的常量模块:

public class ConstantsModule extends AbstractModule {
  @Override
  public void configure() {
    requestStaticInjection(Constants.class);
    final MapBinder<String, Authorizer> mapBinder = MapBinder.newMapBinder(binder(), String.class, Authenticator.class);
    mapBinder.addBinding(AUTH_METHOD_ONE).to(MethodOneAuthorizer.class);
    mapBinder.addBinding(AUTH_METHOD_TWO).to(MethodTwoAuthorizer.class);
  }
}

以及一个示例用法:

public class AuthorizationOrchestrator {
  private static Authorizer getAuthorizer(final AuthorizationState state) {
    return state.getMethods().stream()
      .map(AuthorizationApproach::getAuthorizationApproachName)
      .filter(Constants.getAuthMethods().keySet()::contains)
      .findFirst()
      .map(Constants.getAuthMethods()::get)
      .orElse(null);
  }
}

这种方法还需要在单元测试中使用一些 PowerMock。有没有更好的方法:

  • 将授权方法的名称映射到一个Authorizer类,同时将映射保留在一个地方?
  • 将该Constants类用作真正的实用程序类,public static final Map<String, Authorizer> AUTH_METHODS同时仍然能够将授权者注入Map
4

1 回答 1

1

注入一些应该是常数的东西并没有真正的意义。

通过使用静态Constants类,您将在使用您的类的代码中引入非注入依赖Constants项,这与 DI 的全部观点背道而驰——更不用说在测试中更难以模拟静态依赖项了。

还有其他一些可能对您有用的方法。原则上,它们都是相同的解决方案(将Authorizers 注入非静态的东西),但它们有一些不同的细微差别。

  • 使用组合来避免需要实用程序类。制作一个Authorizer由多个Authorizers 组成的实现。组合Authorizer可以在内部委托给正确的“真实”实现。然后你可以在Authorizer任何需要的地方注入一个。根据Authorizer合同的定义方式,这可能是不可能的。

  • 在实用程序类中保留没有任何状态的逻辑。将静态方法的签名更改为getAuthorizer(AuthorizationState state, Map<String, Authorizer> availableAuthorizersByName). 然后,将AUTH_METHODS映射直接注入将调用您的静态getAuthorizer方法的类中,并将映射作为参数之一传递给该方法。

  • 使getAuthorizer()不是静态的。并将地图直接注入AuthorizationOrchestrator.

于 2019-07-09T03:09:31.593 回答