Dagger2 源码分析离不开对 Java 注解的深入理解,以下是 Android 开发者必须掌握的 Java 注解核心知识体系,涵盖定义、元注解、属性、提取及使用场景等关键细节。
注解的定义与作用- 元数据功能:Java 注解用于为代码提供元数据,不直接影响代码执行,但部分类型注解可参与编译或运行时逻辑。
- 标签类比:注解可视为给代码元素(如类、方法)打标签,用于标记或描述其特性。
- 自定义注解:通过 @interface 关键字定义,形式类似接口但需添加 @ 符号。例如:public @interface Test {}
- 使用注解:在类、方法等元素前添加 @注解名 即可应用。例如:@Testpublic class TestAnnotation {}
元注解:注解的注解元注解用于修饰其他注解,提供额外元信息,共有 5 种标准类型:
- @Retention:指定注解的存活周期。
RetentionPolicy.SOURCE:仅保留在源码阶段,编译时丢弃。
RetentionPolicy.CLASS:保留到编译阶段,不加载到 JVM(默认行为)。
RetentionPolicy.RUNTIME:保留至运行时,可通过反射获取。
- @Target:限定注解的应用目标。
常见取值:ElementType.METHOD(方法)、FIELD(字段)、TYPE(类/接口)等。
示例:限制注解仅用于方法:
@Target(ElementType.METHOD)public @interface MethodAnnotation {} - @Documented:将注解包含在 Javadoc 文档中。
- @Inherited:允许子类继承父类的注解(仅对类有效)。
- @Repeatable(Java 1.8+):允许注解重复使用,适用于需多个值的场景。
注解的属性与默认值- 属性定义:注解可包含成员变量(属性),类型限于基本数据类型、类、接口、注解及其数组。
- 默认值:通过 default 关键字指定,未赋值时使用默认值。例如:public @interface Test { int id() default -1; String msg() default "Hello";}
- 属性赋值:使用时在括号内以 属性名=值 形式赋值,多个属性用逗号分隔。例如:@Test(id = 1, msg = "hello annotation")public class TestAnnotation {}
注解的提取:反射机制注解信息通过反射获取,核心方法包括:
注解的典型使用场景- 编译器辅助:提供信息供编译器检测错误或生成警告(如 @Override)。
- 编译时处理:工具利用注解生成代码或文档(如 Lombok、Dagger2 的代码生成)。
- 运行时处理:通过反射读取注解实现动态逻辑(如 Spring 的依赖注入、Retrofit 的接口解析)。
- 非代码部分:注解仅作为元数据存在,不直接参与代码执行。
Dagger2 中的注解应用Dagger2 依赖大量注解实现依赖注入,关键注解包括:
- @Module:标记提供依赖的类,指定依赖的生成方法。
- @Provides:标记方法,表明该方法提供特定类型的依赖。
- @Inject:标记构造函数、字段或方法,声明依赖注入点。
- @Component:连接 @Module 和 @Inject,生成依赖注入的容器。
示例:通过 @Module 和 @Provides 提供依赖,@Inject 注入依赖:
@Modulepublic class AppModule { @Provides String provideString() { return "Hello Dagger2"; }}public class MainActivity { @Inject String message; public MainActivity() { DaggerAppComponent.create().inject(this); // 触发注入 System.out.println(message); // 输出: Hello Dagger2 }}总结- 核心知识:掌握注解定义、元注解(尤其是 @Retention 和 @Target)、属性赋值与反射提取是理解 Dagger2 的基础。
- 实践意义:Dagger2 通过注解实现编译时代码生成,避免反射性能损耗,其注解设计是 Android 依赖注入框架的典范。
- 延伸学习:结合 Retrofit、ButterKnife 等框架的注解使用,深化对元编程的理解。
通过系统掌握这些知识,开发者能更高效地阅读 Dagger2 源码,并灵活运用注解优化 Android 项目架构。