@AutoAnnotation 有什么用?怎么用?

What is @AutoAnnotation for? How could it be used?

https://dagger.dev/multibindings.html, I read about @AutoAnnotation. It has a reference to https://github.com/google/auto/blob/master/value/src/main/java/com/google/auto/value/AutoAnnotation.java.

里面也提到了 https://github.com/google/auto/blob/57dfad360306619a820e6aae4a14a1aa67c29299/value/userguide/howto.md#annotation

我看了,没看懂。

我设法使用

从我的 Android 代码访问它
implementation 'com.google.auto.value:auto-value:1.5.2'
kapt 'com.google.auto.value:auto-value:1.5.2'

还有

android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true

但是我不明白它怎么用。有什么好的使用教程吗?

AutoAnnotation 自动生成一个 class 以与 JDK 相同的方式实现注释接口。

匕首地图键

当通过使用自定义注解作为键的 Dagger 使用 Multibindings 映射时,Dagger 将安装实例 T 或 Provider Provider<T> 到 returned 映射中,使用注释实例本身作为键。为了使这一点更清楚:

@MapKey
@interface YourAnnotation {
  String foo();
}

@Provides @YourAnnotation(foo="bar") YourClass getYourClassForBar() { /* ... */ }

// Dagger will create a multibinding that would allow you to inject this:
@Inject Map<YourAnnotation, YourClass> map;

如果这里唯一重要的是 foo,您也可以使用 unwrapKeys 使地图以字符串而不是 YourAnnotation 为键,但我们假设您需要这个,因为您希望 YourAnnotation将来有多个值。但是 YourAnnotation 的实现从何而来,你应该如何在地图上调用 get

运行时注释

当您注释 Java 元素(通常是 class、方法或字段)时 Java 将 return 该 class 的特定实现的注解。来自 Java tutorial:

@interface ClassPreamble {
   String author();
   String date();
   int currentRevision() default 1;
   String lastModified() default "N/A";
   String lastModifiedBy() default "N/A";
   // Note use of array
   String[] reviewers();
}

// [...]

@ClassPreamble (
   author = "John Doe",
   date = "3/17/2002",
   currentRevision = 6,
   lastModified = "4/12/2004",
   lastModifiedBy = "Jane Doe",
   // Note array notation
   reviewers = {"Alice", "Bob", "Cindy"}
)
public class Generation3List extends Generation2List {/* ... */}

在这种用法中,Generation3List 有一个 ClassPreamble 类型的 Annotation。如果注释在运行时保留(即 ClassPreamble 本身是 annotated with @Retention(RUNTIME)), you can get to it via Generation3List.class.getAnnotations() or Generation3List.class.getAnnotation(ClassPreamble.class)。(也有 declared 对应物以不同方式处理 superclass 注释。)

一旦获得 ClassPreamble 的实例,就可以使用 author()date() 等方法从 class 中检索数据。但是,ClassPreamble 表现为一个接口,并且该注释的实现在 VM 内部。这使得在运行时创建自己的任意 ClassPreamble 实例变得更加困难。

符合注解的实现

因为 YourAnnotation 和 ClassPreamble 是接口,所以您可以创建一个实现。但是,与 VM 的实现相比,该实现不太可能具有 equalshashCode 的匹配实现,因为 JRE 之间的实现可能不同,并且在 Android 中也可能不同。然而,equalshashCode的实现实际上是非常严格规定的in the docs for Annotation:

The hash code of an annotation is the sum of the hash codes of its members (including those with default values), as defined below: The hash code of an annotation member is (127 times the hash code of the member-name as computed by String.hashCode()) XOR the hash code of the member-value, as defined below [...]

Returns true if the specified object represents an annotation that is logically equivalent to this one. In other words, returns true if the specified object is an instance of the same annotation type as this instance, all of whose members are equal to the corresponding member of this annotation, as defined below [...]

这些规则可以手动实现,但是实现起来比较困难,而且如果YourAnnotation或者ClassPreamble的结构发生变化,也会造成负担。尽管 there are reflective solutions to this problem,AutoAnnotation 会自动生成符合要求的代码:

public class YourAnnotations {
  @AutoAnnotation public static YourAnnotation yourAnnotation(String foo) {
    return new AutoAnnotation_YourAnnotations_yourAnnotation(foo);
  }
}

public class ClassPreambles {
  @AutoAnnotation public static ClassPreamble classPreamble(
      String author,
      String date,
      int currentRevision,
      String lastModified,
      String lastModifiedBy,
      String[] reviewers) {
    return new AutoAnnotation_ClassPreambles_classPreamble(
        author,
        date,
        currentRevision,
        lastModified,
        lastModifiedBy,
        reviewers);
  }
}

使用 AutoAnnotation 生成的实现,您可以在 Dagger Multibindings 生成的地图上调用 get(或提供您控制的测试实现),而无需处理特定于注释的 hashCode XOR 或 equals 规则。这在 Dagger 和测试之外很有用,但由于 Dagger 在其映射中使用注释实例,因此您可能需要使用 AutoAnnotation 来创建类似的实例。