【Android】Android 实现一个依赖注入的注解

Android 实现一个依赖注入的注解

🎯 目标功能

  • 自定义注解 @Inject
  • 创建一个 Injector 类,用来扫描并注入对象
  • 支持 Activity 或其他类中的字段注入

🧩 步骤一:定义注解

java 复制代码
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 {
}

🧩 步骤二:实现注入逻辑

java 复制代码
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());
                }
            }
        }
    }
}

🧩 步骤三:使用示例

要实例化的对象类

java 复制代码
import android.util.Log;

public class Service {
    public void doSomething() {
        System.out.println("Service is working");
        Log.i("ServiceTAG", "Service is doSomething");
    }
}

在MainActivity注入

Java 复制代码
public class MainActivity extends AppCompatActivity {

    @Inject
    Service service;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 注入逻辑
        Injector.inject(this); 
        // 使用注入的对象
        service.doSomething(); 
    }
}

✅ 补充建议

  • 为了更灵活,你可以改用 构造器注入单例管理
  • 如果要支持参数构造函数、依赖图、作用域管理,可以逐步扩展。
  • 如果你对性能敏感,可以考虑使用 APT(注解处理器) 生成代码。

逐段解释一下上述代码:

🔧 一、自定义注解 @Inject

Java 复制代码
@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():获取这个类里 声明的所有字段(不管是私有还是公有)。
Java 复制代码
        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():用 默认无参构造函数 实例化对象。

⚠️ 这里假设被注入的类必须有一个无参构造函数。

Java 复制代码
                    field.setAccessible(true);
                    field.set(target, instance);
✅ 解读:
  • setAccessible(true):允许访问私有字段。
  • field.set(target, instance):将我们创建好的实例注入到目标对象的字段中。

Java 复制代码
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException("Failed to inject " + field.getName());
                }
            }
        }
    }
}
✅ 解读:
  • 如果注入失败就打印异常并抛出运行时异常,方便调试。

💡 三、使用方式解析

Java 复制代码
public class MainActivity extends AppCompatActivity {

    @Inject
    Service service;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Injector.inject(this); // 调用注入器注入
        service.doSomething(); // 使用注入后的 service
    }
}
✅ 解读:
  • 使用了 @Inject 标记字段,告诉注入器需要注入这个字段。
  • Injector.inject(this):告诉系统对这个对象(MainActivity)做依赖注入。
  • service.doSomething():使用注入后的对象方法。

📌 总结核心原理

步骤 描述
1 定义注解,告诉系统哪些字段要注入
2 通过反射找出所有有注解的字段
3 为这些字段创建对应实例
4 把实例赋值给这些字段
相关推荐
Libraeking9 小时前
破壁行动:在旧项目中丝滑嵌入 Compose(混合开发实战)
android·经验分享·android jetpack
市场部需要一个软件开发岗位9 小时前
JAVA开发常见安全问题:Cookie 中明文存储用户名、密码
android·java·安全
JMchen12311 小时前
Android后台服务与网络保活:WorkManager的实战应用
android·java·网络·kotlin·php·android-studio
crmscs12 小时前
剪映永久解锁版/电脑版永久会员VIP/安卓SVIP手机永久版下载
android·智能手机·电脑
localbob12 小时前
杀戮尖塔 v6 MOD整合版(Slay the Spire)安卓+PC端免安装中文版分享 卡牌肉鸽神作!杀戮尖塔中文版,电脑和手机都能玩!杀戮尖塔.exe 杀戮尖塔.apk
android·杀戮尖塔apk·杀戮尖塔exe·游戏分享
机建狂魔12 小时前
手机秒变电影机:Blackmagic Camera + LUT滤镜包的专业级视频解决方案
android·拍照·摄影·lut滤镜·拍摄·摄像·录像
hudawei99612 小时前
flutter和Android动画的对比
android·flutter·动画
lxysbly14 小时前
md模拟器安卓版带金手指2026
android
儿歌八万首14 小时前
硬核春节:用 Compose 打造“赛博鞭炮”
android·kotlin·compose·春节
消失的旧时光-194317 小时前
从 Kotlin 到 Dart:为什么 sealed 是处理「多种返回结果」的最佳方式?
android·开发语言·flutter·架构·kotlin·sealed