Dagger2实现依赖注入之深入探究

Dagger2实现原理分析 Dagger是一个依赖注入框架,这个框架往往给人一种“高端,但是却很难用“的感觉。我们在使用或者阅读别人的项目时,往往会陷入dagger搭建的”迷宫里”绕不出来。导致Dagger被认为是android史上”最受冷落的优质库”。本文先通过理清依赖注入的概念,然后详细介绍Dagger一些常见的使用场景和注意事项,最后介绍一下Dagger主要功能实现的原理。帮助大家进行理解。 阅读详情
上一篇文章 Dagger2实现依赖注入之一步一步带你入门已经和大家分享了Dagger2的基本使用,如果你还没学会,可以边看文章边自己操作一遍。

上次说到,第六个步骤需要我们自己去重新编译一下项目,不然是无法执行最后一步的,也就是添加以下代码。
     DaggerPassPortComponent.builder()
                    .applicationComponent(getAppComponent())
                    .passPortModule(new PassPortModule(this))
                    .build()
                    .inject(this);

我们可以看到代码中有个 DaggerPassPortComponent,这个类就是完成依赖关系后重新编译生成的,但是如果编译不过是不会生成这个类的,这里说下,如果在目标类用 @Inject 做了注解的属性但是没有相应地在提供依赖类中写明提供依赖的方法,编译也是不会过的,是不是有点绕,没事,我们看代码。

比如我在 PassPortActivity 中用 @Inject 注解了两个属性,但是我在 PassPortModule 中把 provideIDCard 方法注释掉,那么重新编译之后就会出错。
        @Inject
        IDCardBean mIDCard;

        @Inject
        FamilyRegisterBean mFamilyRegister;

    //    @PerActivity
    //    @Provides
    //    public IDCardBean provideIDCard() {
    //        return new IDCardBean(mView);
    //    }

        @PerActivity
        @Provides
        public FamilyRegisterBean provideFamilyRegister() {
            return new FamilyRegisterBean(mView);
        }







编译成功之后就会生成一个   DaggerPassPortComponent ,那么这是个什么东西呢,我们一步一步看下他的源码,点 builder() 之后看到
    public static Builder builder() {
        return new Builder();
      }

直接就 new 一个 Builder 实例,这个Builder 是他的内部类
     public static final class Builder {
        private PassPortModule passPortModule;

        private ApplicationComponent applicationComponent;

        private Builder() {}

        public PassPortComponent build() {
          if (passPortModule == null) {
            throw new IllegalStateException(PassPortModule.class.getCanonicalName() + " must be set");
          }
          if (applicationComponent == null) {
            throw new IllegalStateException(
                ApplicationComponent.class.getCanonicalName() + " must be set");
          }
          return new DaggerPassPortComponent(this);
        }

        public Builder passPortModule(PassPortModule passPortModule) {
          this.passPortModule = Preconditions.checkNotNull(passPortModule);
          return this;
        }

        public Builder applicationComponent(ApplicationComponent applicationComponent) {
          this.applicationComponent = Preconditions.checkNotNull(applicationComponent);
          return this;
        }
      }



从中也能很清楚看到,里面的 passPortModule 方法可以把你的 Module 传进去,接着再执行 build()方法,这个方法里面先是判空,然后 new 一个 DaggerPassPortComponent实例。
     private DaggerPassPortComponent(Builder builder) {
        assert builder != null;
        initialize(builder);
      }



而 initalize(builder) 中则有以下重要的代码
    this.provideIDCardProvider =
            DoubleCheck.provider(PassPortModule_ProvideIDCardFactory.create(builder.passPortModule));
     
    this.provideFamilyRegisterProvider =
            DoubleCheck.provider(PassPortModule_ProvideFamilyRegisterFactory.create(builder.passPortModule));

    this.passPortActivityMembersInjector =
            PassPortActivity_MembersInjector.create(provideIDCardProvider, provideFamilyRegisterProvider);




可以看出有一个 PassPortModule_ProvideIDCardFactory 和 PassPortModule_ProvideFamilyRegisterFactory,这两个类也是 Dagger2 生成的,点进去 create方法我们可以看到,其实这两个都是生产依赖的工厂类
    public final class PassPortModule_ProvideFamilyRegisterFactory
        implements Factory<FamilyRegisterBean> {
      private final PassPortModule module;

      public PassPortModule_ProvideFamilyRegisterFactory(PassPortModule module) {
        assert module != null;
        this.module = module;
      }

      @Override
      public FamilyRegisterBean get() {
        return Preconditions.checkNotNull(
            module.provideFamilyRegister(), "Cannot return null from a non-@Nullable @Provides method");
      }

      public static Factory<FamilyRegisterBean> create(PassPortModule module) {
        return new PassPortModule_ProvideFamilyRegisterFactory(module);
      }
    }



还有一个 passPortActivityMembersInjector ,create方法也是 new 出一个实例
    public final class PassPortActivity_MembersInjector implements MembersInjector<PassPortActivity> {
     
      private final Provider<IDCardBean> mIDCardProvider;

      private final Provider<FamilyRegisterBean> mFamilyRegisterProvider;

      public PassPortActivity_MembersInjector(
          Provider<IDCardBean> mIDCardProvider,
          Provider<FamilyRegisterBean> mFamilyRegisterProvider) {
        assert mIDCardProvider != null;
        this.mIDCardProvider = mIDCardProvider;
        assert mFamilyRegisterProvider != null;
        this.mFamilyRegisterProvider = mFamilyRegisterProvider;
      }

      public static MembersInjector<PassPortActivity> create(Provider<IDCardBean> mIDCardProvider,
                                                             Provider<FamilyRegisterBean> mFamilyRegisterProvider) {
        
          return new PassPortActivity_MembersInjector(mIDCardProvider, mFamilyRegisterProvider);
      }

      @Override
      public void injectMembers(PassPortActivity instance) {
        if (instance == null) {
          throw new NullPointerException("Cannot inject members into a null reference");
        }
        instance.mIDCard = mIDCardProvider.get();
        instance.mFamilyRegister = mFamilyRegisterProvider.get();
      }

      public static void injectMIDCard(
          PassPortActivity instance, Provider<IDCardBean> mIDCardProvider) {
        instance.mIDCard = mIDCardProvider.get();
      }

      public static void injectMFamilyRegister(
          PassPortActivity instance, Provider<FamilyRegisterBean> mFamilyRegisterProvider) {
        instance.mFamilyRegister = mFamilyRegisterProvider.get();
      }
    }



上述源码中的 provider 其实就是一个接口,里面只有一个方法 get()
    public interface Provider<T> {

        /**
         * Provides a fully-constructed and injected instance of {@code T}.
         *
         * @throws RuntimeException if the injector encounters an error while
         *  providing an instance. For example, if an injectable member on
         *  {@code T} throws an exception, the injector may wrap the exception
         *  and throw it to the caller of {@code get()}. Callers should not try
         *  to handle such exceptions as the behavior may vary across injector
         *  implementations and even different configurations of the same injector.
         */
        T get();
    }

那么在  DaggerPassPortComponent 调用 inject()方法的时候,实际就是调用  passPortActivityMembersInjector 中的  injectMembers()方法,就是在这步真正实现了依赖注入。
    @Override
      public void injectMembers(PassPortActivity instance) {
        if (instance == null) {
          throw new NullPointerException("Cannot inject members into a null reference");
        }
        instance.mIDCard = mIDCardProvider.get();
        instance.mFamilyRegister = mFamilyRegisterProvider.get();
      }



细心的朋友已经知道,mFamilyRegisterProvider.get() 实际就是  PassPortModule_ProvideFamilyRegisterFactory 中的 get()方法,里面就是你在module里面写的提供依赖的方法。
     @Override
      public FamilyRegisterBean get() {
        return Preconditions.checkNotNull(
            module.provideFamilyRegister(), "Cannot return null from a non-@Nullable @Provides method");
      }



到此为止,Dagger2的依赖注入流程就和大家分享完了,其实生成的代码都比较简单,大家可以自己再去跟一下代码,看完之后你会对Dagger2有更深的了解。



保姆级教程:用Python+Mediapipe实时捕捉手势,驱动Unity虚拟手模型(附完整源码) 本文详细介绍了如何利用Python的Mediapipe库和Unity实现实时手势识别与虚拟手模型驱动。通过OpenCV进行图像采集,Mediapipe提供21个手部关键点识别,结合UDP通信协议实现Python与Unity之间的低延迟数据传输。教程包含完整源码、环境配置、核心代码实现及性能优化技巧,适用于VR教育、游戏开发等需要自然交互的场景。 阅读详情

相关推荐

AI 技术新手入门与实战指南

仅仅能对话还不够,实际应用中,我们往往需要让 AI 处理特定的业务数据。比如,从日志文件中提取错误码,或者将非结构化的用户反馈整理成 JSON 格式。这时候,自定义输入和严格的结果验证就显得尤为重要。假设我们需要让 AI 分析一段服务器日志,并只返回错误的级别和简述。请分析以下日志片段,提取所有 ERROR 级别的信息。要求输出格式为 JSON 列表,包含 'timestamp' 和 'message' 两个字段。不要输出任何多余的解释文字。日志内容: {

2600_94936330的博客 2680

Dagger2详解-从代码分析其原理

Dagger2基本概念请移步官方文档,或者我的翻译。架构方面请关注GitHub(MVP+Retrofit+Dagger2+Okhttp)及我的文章Android UI框架快速搭建实践Dagger2是Dagger1的分支,由谷歌公司接手开发,目前的版本是2.0。Dagger2解决问题的基本思想是:利用生成和写的代码混合达到看似所有的产生和提供依赖的代码都是手写的样子。如果我们将Dagger2和1比较...

371

Cisco三层交换机的详细配置

** 本文适用于新手小白以及微微基础的同学来用于参考,实验是在Cisco Packet Tracer Student 进行,实验最终效果如图所示,所有命令配置与图中的一致。 使用到的机器型号为:五台电脑,一台服务器,三个普通交换机(2960型号),一个三层交换机(3560-24PS),两台普通服务器(2811) 文章目录一、什么是三层交换机二、配置交换机步骤1.配置二层交换机2.配置三层交换机3.配置两台路由器以及最后一台电脑 一、什么是三层交换机 1.三层交换机 = 三层路由+二层交换机 2.工作在

真正的大师,永远都怀着一颗学徒的心。 4万+

终极TensorFlow 2.3教程:从零开始快速掌握深度学习全栈技能

TensorFlow-Course是一个革命性的开源教程项目,专为想要快速掌握TensorFlow 2.3全栈技能的初学者和普通用户设计。这个项目提供了简单易用、随时可用的TensorFlow教程,帮助用户从基础概念到高级应用全面掌握深度学习框架。无论你是机器学习新手还是有经验的开发者,这个教程都能让你快速上手TensorFlow 2.3,构建强大的深度学习模型。🎯 ## 📊 为什么选择Te

gitblog_00070的博客 452

如何使用superpowers

"这个 bug 帮我修一下" → 我会自动走 systematic-debugging → TDD → verify 流程。- "帮我添加一个登录功能" → 我会自动走 brainstorming → plan → TDD → verify 流程。只要任务有 1% 的可能性适用某个技能,我就会先调用它再行动。→ TDD(测试驱动开发)→ verification(验证)→ code review(代码审查)提出需求 → brainstorming(头脑风暴)→ writing-plans(编写计划)

xiaojingjianqiang的博客 610

【软碟通 | UltraISO】刻录光盘教程(制作U盘启动盘)

前言 今天老师说办公室的电脑有点卡,让我给重新安装一个 Windows 7 系统。于是就用软碟通(UltraISO)在 U 盘上刻录了一个 Windows 7 镜像,然后给老师重装了系统。顺便把制作 U 盘启动盘的教程也分享给大家。 软件 UltraISO v9.7.1.3519:点击跳转(密码:dd2k) 教程 将 U 盘插到电脑上,然后鼠标右击选择格式化(制作启动盘必须格式化) 点击文件-打开 选择下载好的系统镜像(如:Windows 7) 点击启动-写入硬盘映像 选择硬盘

XavierJ的博客 2万+

Nest.js 实战系列第二篇-实现注册、扫码登陆、jwt认证等

大厂技术高级前端Node进阶点击上方程序员成长指北,关注公众号回复1,加入高级Node交流群大家好我是考拉????,这是Nest.js 实战系列第二篇,我要用最真实的场景让你学会使用...

程序员成长指北 8439

Swin Transformer 类可视化(grad CAM)

完整代码 from pytorch_grad_cam import GradCAM, ScoreCAM, GradCAMPlusPlus, AblationCAM, XGradCAM, EigenCAM from pytorch_grad_cam.utils.image import show_cam_on_image from torchvision.models import resnet50 import glob from demo import parse_option from models i

G果的博客 6639

Dagger2解析(实例+源码)

Dagger is a fully static, compile-time dependency injection framework for both Java and Android. It is an adaptation of an earlier versioncreated by Square and now maintained by Google. Dagger aims to...

weixin_34205076的博客 276

第4章 部署负载均衡 Keepalived + HAProxy

本章在所有 Master 节点部署 Keepalived + HAProxy,为 kube-apiserver 提供高可用入口。Keepalived 实现 VIP(192.168.3.59)漂移,HAProxy 轮询转发请求至三个 Master 的 6443 端口(监听 6444 避免冲突)。健康检查脚本连续 5 次失败则停止 Keepalived,触发 VIP 自动切换。本章还包含配置详解、日常运维和问题排查。

幸福街--linux技术分享 120

第14.5章 高翔博士最新开源框架Lightning-LM源码解读(五):揭秘位姿图优化核心模块,从数学原理到代码实现

本文介绍了Lightning-LM框架中的位姿图优化(PGO)模块实现。该模块通过融合多源定位信息(激光定位、激光里程计、DR等),构建并优化位姿图来获得更精确的位姿估计。 主要内容包括: 模块概况与数据流程:初始化配置→添加PGO帧→分配位姿→优化求解→更新位姿→滑动窗口 16个核心函数详解:从构造函数到边缘化处理,涵盖完整的PGO工作流程 关键技术点:噪声参数设置、优化问题构建、约束添加、异常值处理等 关键数据结构:帧队列管理、顶点和边构建、优化统计信息收集 该PGO模块采用增量式优化方式,支持多种约束

行知SLAM 1216

node.js 中间件_Node.js中的Passport中间件(模块)

node.js 中间件Hi! Welcome to Node.js Authentication Series, where we'll study and program the passport module or middleware. 嗨! 欢迎使用Node.js身份验证系列 ,我们将在其中研究和编程通行证模块或中间件 。 Nowadays, an important tool in ...

cumt951045的博客 553

用 SAP HANA SDA 访问 PostgreSQL:从可行性到落地实践的完整指引

摘要:SAP HANA可通过SDA/SDI技术访问PostgreSQL数据库,支持数据虚拟化和实时复制。主要实现路径包括:1)使用Camel JDBC适配器创建虚拟表进行联邦查询;2)利用PostgreSQL Log Reader适配器实现变更数据捕获(CDC)。实施时需配置Data Provisioning Agent,注意权限和网络要求。官方文档指出,通过SDI+DP Agent的方式比直接SDA连接更稳定可靠。虚拟化查询时,HANA会自动将SQL下推到PostgreSQL执行,优化性能。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 253

Dagger2的介绍和配置

前言 Dagger2的介绍和配置 Dagger2基础的使用 Dagger2进阶-编译生成源码解读 Dagger2进阶-范围的控制(Scope和Singleton) Dagger2进阶-Scope的源码探究 项目源码传送门​​​​​​​ Dagge...

木木baby的博客 1068

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Dagger2——DI依赖注入——IOC原则的实现者

《如何获得完全松耦合的程序设计》 IoC原则、DIP原则、DI设计模式可以帮助我们获得完全松耦合的程序设计。而Dagger2则是实现了依赖注入(DI)设计模式的框架,也就是它实现了IoC原则。 简而言之,Dagger2在遵循IoC原则下帮助我们创建依赖对象。我大概讲一下DI设计模式:比说A类依赖B类,那么我们通过在A类外面创建B类的对象,再将其注入A类。需要有个第三方帮我们把这件事做了(IoC的体现),那么Dagger2就是这个第三方。 Dagger2是基于java规范要求,使用注解的方式生成代码。我们通过

weixin_40763897的博客 2107

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

一文看懂依赖注入(Dagger2)

一句话解释依赖注入(DI)的作用,就是。

weixin_51020083的博客 983

Android _ 从 Dagger2 到 Hilt 玩转依赖注入(一)

子组件是继承并扩展父组件的对象图的组件,子组件中的对象就可以依赖于父组件中提供的对象,但是父组件不能依赖于子组件依赖的对象(简单的包含关系,对吧?我们继续通过一个简单的例子来展开:假设我们有一个登录模块 LoginActivity,它依赖于 LoginModel。我们的需求是定义一个子组件,它的声明周期只在一次登录流程中存在。在。

2401_84009317的博客 830

你还停留在使用Dagger2吗? 带你一步一步走进Dagger2的世界

Dagger2是一个依赖注入框架 1.什么是依赖注入? 就是目标类中所依赖的其他的类的初始化过程,不是通过手动编码的方式创建 将其他的类初始化好的实例自动注入到我们的目标类当中。它也是面向对象的一种设计模式, 主要作用就是降低我们程序的耦合。 讲述两个场景来描述一下Dagger2: 1.在一个对象里创建另一个对象的实例。这种行为就会产生耦合现象。导致代码难以维护。 2.Picasso...

wk_先森的博客 2万+

如何用Dagger 2在Kotlin Android应用中实现依赖注入:基于PhotoAffix的完整教程

PhotoAffix 是一款用 Kotlin 编写的 Android 照片拼接应用,它将 Dagger 2 依赖注入框架运用得恰到好处:通过 1 个 AppComponent 和 5 个 Module,把图片引擎、用户偏好、协程调度器等依赖自动装配到界面层。这篇完整教程带你从核心概念到实战源码,快速掌握 Dagger 2 依赖注入的全部用法。 [![PhotoAffix Android 照片拼接

gitblog_00726的博客 971

dagger2实现原理

首先,我们定义 AppComponent 和 AppModule。Java6}79@Module15 }16}这里,@Component注解定义了一个组件,并指定了模块。@Module注解定义了一个模块,@Provides注解则指定了如何提供 MyService 实例。

VitorLiu的博客 1320

用 Dagger 2 实现依赖注入

Dagger 2 为你解析这些依赖,并生成把它们绑定在一起的代码。也有很多其它的 Java 依赖注入框架,但它们中大多数是有缺陷的,比如依赖 XML,需要在运行时验证依赖,或者在起始时造成性能负担。 Dagger 2 纯粹依赖于 Java 注解解析器以及编译时检查来分析并验证依赖。它被认为是目前最高效的依赖注入框架之一。

Treasure 287

Dagger2 依赖注入的原理分析

Dagger2 依赖注入的原理分析 因为 Dagger2 的使用情况很多,这里只对基本的使用方法进行分析。 以一个简单依赖注入举例如下: 创建 Watch 类如下: public class Watch { public Watch() { } public String work() { return "work"; } } 创建 Watc...

okclouderx的博客 451

Andriod Dagger2依赖注入

Android Dagger前言:学习Dagger首先要了解什么是依赖注入(Dependency Injection),为什么需要依赖注入,了解这些以后就可以进入Dagger的学习,现在大部分的项目都在使用Dagger2,我们先就Dagger2进行学习,慢慢了解注入的机制。what and why(Dependency Injection)what:依赖注入(DI):就好比一个人去淘宝买一件衣服,他

L_bsSua的博客 441

使用Dagger 2进行依赖注入

转: 使用Dagger 2进行依赖注入 使用Dagger 2进行依赖注入 发表于 2015-08-06   |   分类于 Android   |   8条评论 0. 前言 Dagger2是首个使用生成代码实现完整依赖注入的框架,极大减少了使用者的编码负担, 本文主要介绍如何使用Dagger2进行依赖注入。如果你不还不了解依赖注入,请看这一篇。

wxx614817的专栏 535

android dagger2 讲解,用Dagger2在Android中实现依赖注入

依赖注入这个模式(模式已经用烂了,这里再烂一次)是用来给应用的各部分解耦的。使应用开发更加可扩展,更容易维护。通过本文你会学到如何使用Dagger2来处理依赖。简介如果以对象需要另外的一个对象才能完成一个完整功能的话,那么这里就存在一个依赖。比如,悟空要用金箍棒才能三打白骨精,要筋斗云才能十万八千里。悟空有对金箍棒和筋斗云的依赖。你可以在悟空对象里初始化金箍棒,也可以用一个工厂方法批量生产金箍棒。...

weixin_30877689的博客 368

依赖注入框架Dagger2

什么的依赖注入 在软件工程中,依赖注入是实现控制反转的方式之一。百度百科中对于控制反转的解释如下:控制反转(Inversion of Control,英文缩写为IoC)把创建对象的权利交给框架。我们可以举例来说明一下,在开发中我们经常有类组合的情况,例如Student类中引用了School类,用于描述学生的学校信息,那么这就是典型的组合,再具体点的例子:假设我们的网络请求类RetrofitMan...

李锦锋 532
上一篇: Dagger2实现依赖注入之一步一步带你入门
Interface_l
博客等级 码龄12年 0粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值