【问题标题】:Create MessageDigest with Guice使用 Guice 创建 MessageDigest
【发布时间】:2022-03-26 02:00:24
【问题描述】:

我正在尝试找到一种使用 Guice 初始化 MessageDigest 的方法。目前我有这个:

public class MyClass {

    MessageDigest md;
    
    public MyClass() {
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
....
}

我想看看它是否可以写成:

@Inject
MessageDigest md;

但是如何让 Guice 拨打 MessageDigest.getInstance("MD5")

【问题讨论】:

    标签: java guice


    【解决方案1】:

    MessageDigest 是一个很特别的班级。它的所有实例仅供一次使用。因此必须非常小心地注射。

    首先,您必须告诉 Guice 创建该类的多个实例。这是在您的Module 类中完成的。

    @Provides
    MessageDigest provideMD5() throws NoSuchAlgorithmException {
      return MessageDigest.getInstance("MD5");
    }
    

    然后,一旦您的提供程序可以每次都创建实例,它被注入,您可能实际上并不希望每个注入实例只需要一个实例。因此,您可能必须执行以下操作:

    @Inject
    Provider<MessageDigest> md5Provider;
    
    ...
    
    // Later in the class
    MessageDigest md5 = md5Provider.get();
    

    【讨论】:

    • 这行得通。但仍然需要尝试更多类似的课程。要使用 @Provides 注释,下面是一个示例:tutorialspoint.com/guice/guice_provides_annotation.htm
    • 为此使用 Guice Provider 作为反模式。 Provider 有自己的 Guice 语义,因此它要求用户知道必须如何注入这个特定的绑定。如果您使用具有中性语义的 Supplier 之类的东西,那是不必要的,出错是不可能的。
    • @Gene Provider 来自 javax.inject.*jakarta.inject.*,因为 Guice 建议使用他们上面的那些......而这些是 Java 标准。此外,Provider 可以并且应该抛出 ExceptionSupplier 不应该,因为它没有记录它可以。
    【解决方案2】:

    编辑

    我不知道MessageDigest 是一次性使用类。您展示了该类的注入,根据定义,该类不能提供多个实例。所以这个问题是有缺陷的。

    您必须通过绑定创建 MD 而不是 MD 本身的工厂函数来解决此问题。例如。供应商:

    final MessageDigestModule extends AbstractModule {
      @Provide
      Supplier<MessageDigest> provideMd5Digest() {
        return () -> MessageDigest.getInstance("MD5");
      }
    }
    

    然后在创建注入器时,安装new MessageDigestModule()。 您将使用@Inject Supplier&lt;MessageDigest&gt; md5DigestSupplier;。在你需要的地方,你会说md5DigestSupplier.get()

    如果您需要不止一种MessageDigest,那么您应该声明注释并使用它们来分隔绑定。

    @BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
    @interface Md5 {}
    @BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
    @interface Sha256 {}
    

    接着

    final MessageDigestModule extends AbstractModule {
      @Provide
      @Md5
      Supplier<MessageDigest> provideMd5Digest() {
        return () -> MessageDigest.getInstance("MD5");
      }
      @Provide
      @Sha256
      Supplier<MessageDigest> provideMd5Digest() {
        return () -> MessageDigest.getInstance("SHA-256");
      }
    }
    

    最后:

    @Inject
    @Sha256
    Supplier<MessageDigest> sha128DigestSupplier;
    

    【讨论】:

    • 不起作用,因为 MessageDigest 只是一个一次性类。如果您有两个注入的实例,它们将共享同一个一次性实例,这将非常混乱!
    • 但这非常有帮助。我在其他课程中也遵循了这一点。
    • 好的。这个问题通过显示单个 MessageDigest 的注入来误导我。我已经更新了它。 @OlivierGrégoire
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 2013-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多