AutoAnnotation 自动生成一个类,该类实现注解接口的方式与 JDK 相同。
匕首映射键
当通过 Dagger 使用自定义注解作为其键的 Multibindings 映射时,Dagger 将使用注解实例本身作为键将实例 T 或 Provider Provider<T> 安装到返回的映射中。为了更清楚地说明这一点:
@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 使映射由String 而不是YourAnnotation 键控,但假设您希望这样做,因为您希望YourAnnotation 将来有多个值.但是YourAnnotation 的实现是从哪里来的,你应该如何在地图上调用get?
运行时注解
当您注释 Java 元素(通常是类、方法或字段)时,Java 将返回该类注释的特定实现。来自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)),您可以通过Generation3List.class.getAnnotations() 或Generation3List.class.getAnnotation(ClassPreamble.class) 获取它。 (也有声明的对应物以不同的方式处理超类注解。)
一旦获得 ClassPreamble 的实例,就可以使用 author() 和 date() 等方法从类中检索数据。但是,ClassPreamble 充当接口,并且该注释的实现在 VM 内部。这使得在运行时创建您自己的任意 ClassPreamble 实例变得更加困难。
符合注释的实现
因为 YourAnnotation 和 ClassPreamble 是接口,您可以只创建一个实现。但是,与 VM 的实现相比,该实现不太可能具有匹配的 equals 和 hashCode 实现,因为 JRE 之间的实现可能会有所不同,并且在 Android 中也可能会有所不同。不过equals和hashCode的实现其实和in the docs for Annotation的规定非常紧密:
注解的哈希码是其成员(包括具有默认值的)哈希码的总和,定义如下:注解成员的哈希码是(成员名称哈希码的127倍)由 String.hashCode()) 计算的成员值的哈希码 XOR,定义如下 [...]
如果指定的对象表示一个逻辑上等同于该对象的注释,则返回 true。换句话说,如果指定对象是与此实例相同的注解类型的实例,则返回true,其所有成员都等于此注解的相应成员,如下定义[...]
可以手动实现这些规则,但是很难做到,而且如果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 来创建类似的实例是有道理的。