【问题标题】:Inject Dependency to Utility Class Map向实用程序类映射注入依赖项
【发布时间】:2019-07-08 19:27:53
【问题描述】:

我有一个实用程序/常量类,其中包含一个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&lt;String, Authorizer&gt; AUTH_METHODS 一起使用,同时仍然能够将授权者注入Map

【问题讨论】:

    标签: java dependency-injection guice utility-method


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-26
      • 2016-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多