将依赖项注入实用程序类映射

时间:2019-07-08 19:27:53

标签: java dependency-injection guice utility-method

我有一个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中吗?

1 个答案:

答案 0 :(得分:1)

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

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

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

  • 使用合成避免使用实用程序类。制作由多个Authorizer组成的Authorizer实现。复合Authorizer可以在内部委派给正确的“真实”实现。然后,您只需在需要的任何位置注入一个Authorizer。取决于Authorizer合同的定义方式,可能无法启用。

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

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