【Android】Android 实现一个依赖注入的注解
Android 实现一个依赖注入的注解
🎯 目标功能
- 自定义注解
@Inject
- 创建一个
Injector
类,用来扫描并注入对象 - 支持 Activity 或其他类中的字段注入
🧩 步骤一:定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
}
🧩 步骤二:实现注入逻辑
import java.lang.reflect.Field;public class Injector {public static void inject(Object target) {Class<?> clazz = target.getClass();Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {if (field.isAnnotationPresent(Inject.class)) {try {Class<?> type = field.getType();Object instance = type.newInstance(); // 也可以用构造器缓存池优化field.setAccessible(true);field.set(target, instance);} catch (Exception e) {e.printStackTrace();throw new RuntimeException("Failed to inject " + field.getName());}}}}
}
🧩 步骤三:使用示例
要实例化的对象类
import android.util.Log;public class Service {public void doSomething() {System.out.println("Service is working");Log.i("ServiceTAG", "Service is doSomething");}
}
在MainActivity注入
public class MainActivity extends AppCompatActivity {@InjectService service;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 注入逻辑Injector.inject(this); // 使用注入的对象service.doSomething(); }
}
✅ 补充建议
- 为了更灵活,你可以改用 构造器注入 或 单例管理。
- 如果要支持参数构造函数、依赖图、作用域管理,可以逐步扩展。
- 如果你对性能敏感,可以考虑使用 APT(注解处理器) 生成代码。
逐段解释一下上述代码:
🔧 一、自定义注解 @Inject
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
}
✅ 解读:
- @Target(ElementType.FIELD)
表示这个注解只能用于 字段上,不能用于类、方法等。 - @Retention(RetentionPolicy.RUNTIME)
表示这个注解在 运行时依然存在,这样我们就可以通过反射获取它。 - public @interface Inject {}
这是定义了一个名为 Inject 的注解,它 不包含任何参数,只作为标记使用。
🧠 二、注入器类 Injector
public class Injector {public static void inject(Object target) {Class<?> clazz = target.getClass();Field[] fields = clazz.getDeclaredFields();
✅ 解读:
inject(Object target)
:这是一个静态方法,接收需要注入依赖的对象,比如Activity
。target.getClass()
:获取目标类的Class
对象。clazz.getDeclaredFields()
:获取这个类里 声明的所有字段(不管是私有还是公有)。
for (Field field : fields) {if (field.isAnnotationPresent(Inject.class)) {
✅ 解读:
-
遍历所有字段,检查有没有使用我们自定义的
@Inject
注解。try {Class<?> type = field.getType();Object instance = type.newInstance(); // 创建实例
✅ 解读:
field.getType()
:获取字段的类型,比如是Service.class
。type.newInstance()
:用 默认无参构造函数 实例化对象。
⚠️ 这里假设被注入的类必须有一个无参构造函数。
field.setAccessible(true);field.set(target, instance);
✅ 解读:
setAccessible(true)
:允许访问私有字段。field.set(target, instance)
:将我们创建好的实例注入到目标对象的字段中。
} catch (Exception e) {e.printStackTrace();throw new RuntimeException("Failed to inject " + field.getName());}}}}
}
✅ 解读:
- 如果注入失败就打印异常并抛出运行时异常,方便调试。
💡 三、使用方式解析
public class MainActivity extends AppCompatActivity {@InjectService service;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Injector.inject(this); // 调用注入器注入service.doSomething(); // 使用注入后的 service}
}
✅ 解读:
- 使用了
@Inject
标记字段,告诉注入器需要注入这个字段。 Injector.inject(this)
:告诉系统对这个对象(MainActivity)做依赖注入。service.doSomething()
:使用注入后的对象方法。
📌 总结核心原理
步骤 | 描述 |
---|---|
1 | 定义注解,告诉系统哪些字段要注入 |
2 | 通过反射找出所有有注解的字段 |
3 | 为这些字段创建对应实例 |
4 | 把实例赋值给这些字段 |