我有一个Utility / constants类,其中包含一个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吗?

最佳答案

注入原本应该是常量的东西真的没有任何意义。

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

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


使用组合避免使用实用程序类。制作由多个Authorizer组成的Authorizer实现。复合Authorizer可以在内部委派给正确的“真实”实现。然后,您只需在需要的任何地方注入一个Authorizer。取决于Authorizer合同的定义方式,可能无法启用。
保持逻辑在实用程序类中没有任何状态。将静态方法的签名更改为getAuthorizer(AuthorizationState state, Map<String, Authorizer> availableAuthorizersByName)。然后,将AUTH_METHODS映射直接注入到将要调用静态getAuthorizer方法的类中,并将该映射作为方法的参数之一传递给该方法。
使getAuthorizer()不是静态的。并将地图直接注入到AuthorizationOrchestrator的实例中。

关于java - 将依赖项注入(inject)实用程序类映射,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56941442/

10-10 20:08