依赖注入和Dagger2

期货缠论实战:文华财经笔中枢指标公式解析与博易大师应用指南 本文深入解析期货缠论实战中的文华财经笔中枢指标公式及其在博易大师平台的应用技巧。详细介绍了笔中枢指标的核心逻辑、公式拆解、参数设置及多周期联合作战策略,帮助交易者提升市场分析能力与交易胜率。特别适合期货交易者学习缠论指标的实际应用。 阅读详情

1.依赖

如果在 Class A 中,有 Class B 的实例,则称 Class A 对 Class B 有一个依赖。例如下面类 Human 中用到一个 Father 对象,我们就说类 Human 对类 Father 有一个依赖。

public class Human {
    ...
    Father father;
    ...
    public Human() {
        father = new Father();
    }
}

仔细看这段代码我们会发现存在一些问题:

(1). 如果现在要改变 father 生成方式,如需要用new Father(String name)初始化 father,需要修改 Human 代码;
(2). 如果想测试不同 Father 对象对 Human 的影响很困难,因为 father 的初始化被写死在了 Human 的构造函数中;
(3). 如果new Father()过程非常缓慢,单测时我们希望用已经初始化好的 father 对象 Mock 掉这个过程也很困难。

2.依赖注入

上面将依赖在构造函数中直接初始化是一种 Hard init 方式,弊端在于两个类不够独立,不方便测试。我们还有另外一种 Init 方式,如下:

public class Human {
    ...
    Father father;
    ...
    public Human(Father father) {
        this.father = father;
    }
}

上面代码中,我们将 father 对象作为构造函数的一个参数传入。在调用 Human 的构造方法之前外部就已经初始化好了 Father 对象。像这种非自己主动初始化依赖,而通过外部来传入依赖的方式,我们就称为依赖注入。
现在我们发现上面 1 中存在的两个问题都很好解决了,简单的说依赖注入主要有两个好处:

(1). 解耦,将依赖之间解耦。
(2). 因为已经解耦,所以方便做单元测试,尤其是 Mock 测试。

3. Java 中的依赖注入

依赖注入的实现有多种途径,而在 Java 中,使用注解是最常用的。通过在字段的声明前添加 @Inject 注解进行标记,来实现依赖对象的自动注入。

public class Human {
    ...
    @Inject Father father;
    ...
    public Human() {
    }
}

上面这段代码看起来很神奇:只是增加了一个注解,Father 对象就能自动注入了?这个注入过程是怎么完成的?
实质上,如果你只是写了一个 @Inject 注解,Father 并不会被自动注入。你还需要使用一个依赖注入框架,并进行简单的配置。现在 Java 语言中较流行的依赖注入框架有 Google Guice、Spring 等,而在 Android 上比较流行的有 RoboGuice、Dagger 等。其中 Dagger 是我现在正在项目中使用的。 如果感兴趣,你可以到 Dagger 实现原理解析 了解更多依赖注入和 Dagger 实现原理相关信息。

4.Dagger2

为什么是Dagger2

无论是构造函数注入还是接口注入,都避免不了要编写大量的模板代码。机智的猿猿们当然不开心做这些重复性的工作,于是各种依赖注入框架应用而生。但是这么多的依赖注入框架为什么我们却偏爱Dagger2呢?我们先从Spring中的控制反转(IOC)说起。

谈起依赖注入,做过J2EE开发的同学一定会想起Spring IOC,那通过迷之XML来配置依赖的方式真的很让人讨厌;而且XML与Java代码分离也导致代码链难以追踪。之后更加先进的Guice(Android端也有个RoboGuice)出现了,我们不再需要通过XML来配置依赖,但其运行时实现注入的方式让我们在追踪和定位错误的时候却又万分痛苦。开篇提到过Dagger就是受Guice的启发而开发出来的;Dagger继承了前辈的思想,在性能又碾压了它的前辈Guice,可谓是长江后浪推前浪,前浪死在沙滩上。

又如开篇我在简介中说到的,Dagger是一种半静态半运行时的DI框架,虽说依赖注入是完全静态的,但是生成有向无环图(DAG)还是基于反射来实现,这无论在大型的服务端应用还是在Android应用上都不是最优方案。升级版的Dagger2解决了这一问题,从半静态变为完全静态,从Map式的API变成申明式API(@Module),生成的代码更优雅高效;而且一旦出错我们在编译期间就能发现。所以Dagger2对开发者的更加友好了,当然Dagger2也因此丧失了一些灵活性,但总体来说利还是远远大于弊的。

前面提到这种A B C D E连续依赖的问题,一旦E的创建方式发生了改变就会引发连锁反应,可能会导致A B C D都需要做针对性的修改;但是骚年,你以为为这仅仅是工作量的问题吗?更可怕的是我们创建A时需要按顺序先创建E D C B四个对象,而且必须保证顺序上是正确的。Dagger2就很好的解决了这一问题(不只是Dagger2,在其他DI框架中开发者同样不需要关注这些问题)。

Dagger2注解

开篇我们就提到Dagger2是基于Java注解来实现依赖注入的,那么在正式使用之前我们需要先了解下Dagger2中的注解。Dagger2使用过程中我们通常接触到的注解主要包括:@Inject, @Module, @Provides, @Component, @Qulifier, @Scope, @Singleten。

@Inject:@Inject有两个作用,一是用来标记需要依赖的变量,以此告诉Dagger2为它提供依赖;二是用来标记构造函数,Dagger2通过@Inject注解可以在需要这个类实例的时候来找到这个构造函数并把相关实例构造出来,以此来为被@Inject标记了的变量提供依赖;

@Module:@Module用于标注提供依赖的类。你可能会有点困惑,上面不是提到用@Inject标记构造函数就可以提供依赖了么,为什么还需要@Module?很多时候我们需要提供依赖的构造函数是第三方库的,我们没法给它加上@Inject注解,又比如说提供以来的构造函数是带参数的,如果我们之所简单的使用@Inject标记它,那么他的参数又怎么来呢?@Module正是帮我们解决这些问题的。

@Provides:@Provides用于标注Module所标注的类中的方法,该方法在需要提供依赖时被调用,从而把预先提供好的对象当做依赖给标注了@Inject的变量赋值;

@Component:@Component用于标注接口,是依赖需求方和依赖提供方之间的桥梁。被Component标注的接口在编译时会生成该接口的实现类(如果@Component标注的接口为CarComponent,则编译期生成的实现类为DaggerCarComponent),我们通过调用这个实现类的方法完成注入;

@Qulifier:@Qulifier用于自定义注解,也就是说@Qulifier就如同Java提供的几种基本元注解一样用来标记注解类。我们在使用@Module来标注提供依赖的方法时,方法名我们是可以随便定义的(虽然我们定义方法名一般以provide开头,但这并不是强制的,只是为了增加可读性而已)。那么Dagger2怎么知道这个方法是为谁提供依赖呢?答案就是返回值的类型,Dagger2根据返回值的类型来决定为哪个被@Inject标记了的变量赋值。但是问题来了,一旦有多个一样的返回类型Dagger2就懵逼了。@Qulifier的存在正式为了解决这个问题,我们使用@Qulifier来定义自己的注解,然后通过自定义的注解去标注提供依赖的方法和依赖需求方(也就是被@Inject标注的变量),这样Dagger2就知道为谁提供依赖了。—-一个更为精简的定义:当类型不足以鉴别一个依赖的时候,我们就可以使用这个注解标示;

@Scope:@Scope同样用于自定义注解,我能可以通过@Scope自定义的注解来限定注解作用域,实现局部的单例;

@Singleton:@Singleton其实就是一个通过@Scope定义的注解,我们一般通过它来实现全局单例。但实际上它并不能提前全局单例,是否能提供全局单例还要取决于对应的Component是否为一个全局对象。

我们提到@Inject和@Module都可以提供依赖,那如果我们即在构造函数上通过标记@Inject提供依赖,有通过@Module提供依赖Dagger2会如何选择呢?具体规则如下:

步骤1:首先查找@Module标注的类中是否存在提供依赖的方法。
步骤2:若存在提供依赖的方法,查看该方法是否存在参数。
a:若存在参数,则按从步骤1开始依次初始化每个参数;
b:若不存在,则直接初始化该类实例,完成一次依赖注入。
步骤3:若不存在提供依赖的方法,则查找@Inject标注的构造函数,看构造函数是否存在参数。
a:若存在参数,则从步骤1开始依次初始化每一个参数
b:若不存在,则直接初始化该类实例,完成一次依赖注入。

1、案例A

Car类是需求依赖方,依赖了Engine类;因此我们需要在类变量Engine上添加@Inject来告诉Dagger2来为自己提供依赖。

public class Car {

    @Inject
    Engine engine;

    public Car() {
        DaggerCarComponent.builder().build().inject(this);
    }

    public Engine getEngine() {
        return this.engine;
    }
}

Engine类是依赖提供方,因此我们需要在它的构造函数上添加@Inject

public class Engine {

    @Inject
    Engine(){}

    public void run(){
        System.out.println("引擎转起来了~~~");
    }
}

接下来我们需要创建一个用@Component标注的接口CarComponent,这个CarComponent其实就是一个注入器,这里用来将Engine注入到Car中。

@Component
public interface CarComponent {
    void inject(Car car);
}

完成这些之后我们需要Build下项目,让Dagger2帮我们生成相关的Java类。接着我们就可以在Car的构造函数中调用Dagger2生成的DaggerCarComponent来实现注入(这其实在前面Car类的代码中已经有了体现)

public Car() {
    DaggerCarComponent.builder().build().inject(this);
}
2、案例B

如果创建Engine的构造函数是带参数的呢?比如说制造一台引擎是需要齿轮(Gear)的。或者Eggine类是我们无法修改的呢?这时候就需要@Module和@Provide上场了。

同样我们需要在Car类的成员变量Engine上加上@Inject表示自己需要Dagger2为自己提供依赖;Engine类的构造函数上的@Inject也需要去掉,应为现在不需要通过构造函数上的@Inject来提供依赖了。

public class Car {

    @Inject
    Engine engine;

    public Car() {
        DaggerCarComponent.builder().markCarModule(new MarkCarModule())
                .build().inject(this);
    }

    public Engine getEngine() {
        return this.engine;
    }
}

接着我们需要一个Module类来生成依赖对象。前面介绍的@Module就是用来标准这个类的,而@Provide则是用来标注具体提供依赖对象的方法(这里有个不成文的规定,被@Provide标注的方法命名我们一般以provide开头,这并不是强制的但有益于提升代码的可读性)。

@Module
public class MarkCarModule {

    public MarkCarModule(){ }

    @Provides Engine provideEngine(){
        return new Engine("gear");
    }
}

接下来我们还需要对CarComponent进行一点点修改,之前的@Component注解是不带参数的,现在我们需要加上modules = {MarkCarModule.class},用来告诉Dagger2提供依赖的是MarkCarModule这个类。

@Component(modules = {MarkCarModule.class})
public interface CarComponent {
    void inject(Car car);
}

Car类的构造函数我们也需要修改,相比之前多了个markCarModule(new MarkCarModule())方法,这就相当于告诉了注入器DaggerCarComponent把MarkCarModule提供的依赖注入到了Car类中。

public Car() {
   DaggerCarComponent.builder()
           .markCarModule(new MarkCarModule())
           .build().inject(this);
}

这样一个最最基本的依赖注入就完成了,接下来我们测试下我们的代码。

public static void main(String[] args){
    Car car = new Car();
    car.getEngine().run();
}
输出

引擎转起来了~~~
FDTD Script命令学习-farfield3d/farfieldux/farfielduy 介绍了farfield3d/farfieldux/farfielduy命令功能,及不同应用语法和参数介绍,以及对官网示例进行介绍。 阅读详情

相关推荐

MobileNet V3 图像分类

MobileNet V3

Henry的博客 1767

Dagger2的入坑指南[捂脸][详]!!

前言  dagger2的文章从寥寥可数到现在的数不胜数,可见其热门程度。 这篇文章主要是记录我对dagger2的理解,从基本使用,到实际运用,由浅入深。以及dagger2的一些变化。 希望大家能取其精华,去其糟粕,谢谢。 目录结构 前言 为什么要使用dagger2 从需求的角度 从开发者的角度 基本的使用 inject Component Module Provides 基本

L 4130

Duilib的简单使用(五、DuiDesigner/DuiEditor的下载编译)

一、前言 在Duilib的简单使用(一、duilib demo)中我们介绍了利用duilib简单的构造一个项目 在Duilib的简单使用(二、xml实现界面与业务分离)中我们介绍了XML在duilib中的使用 在Duilib的简单使用(三、界面逻辑交互)中我们已经知道如何简单的进行界面的交互 在Duilib的简单使用(四、换肤)中,我们提了一下Duilib强大的一键换肤功能。 通过之前的说明,我们知道duilib是通过xml来分离界面和业务逻辑的,但是xml如果不能预览,那每次敲一个再运行一下看看效果,这不

LyRics1996的博客 2884

安卓Dagger框架:依赖注入实践与应用

Dagger是适用于Android和Java生态系统的强大依赖注入(Dependency Injection, DI)工具,以其编译时生成代码和高效的运行时性能而著称。本文旨在深入探讨Dagger的核心概念、工作流程、优缺点以及实际代码示例,以便开发者更好地理解并有效利用这一框架来优化安卓应用的设计与开发。

wlred1980的博客 1436

S32K344 Bootloader实战:一个按键实现从Boot到App的无缝跳转(附完整代码)

本文详细介绍了基于NXP S32K344微控制器的Bootloader开发实战,重点解析如何通过一个硬件按键实现从Boot到App的可靠跳转。内容涵盖内存分区规划、中断向量表重映射、外设初始状态管理等核心要素,并提供了完整的代码示例和调试技巧,适用于汽车电子和工业控制等高可靠性应用场景。

weixin_29192365的博客 307

基于STM32的多模态智能风扇控制系统设计与实现

本文详细介绍了基于STM32单片机的多模态智能风扇控制系统的设计与实现。系统集成了红外遥控、蓝牙手机控制及人体感应等多模态交互方式,通过PWM技术实现无级调速,并设计了安全优先的控制逻辑。文章从硬件选型、核心原理、软件编程到系统调试,提供了完整的实战指南,适合嵌入式开发爱好者学习与实践。

weixin_28285943的博客 238

Dagger2 的使用与基本原理

使用 Dagger2 的最佳做法:如果有可能,通过@Inject进行构造函数注入,以向 Dagger 图中添加类型。使用@Binds告知 Dagger 接口应采用哪种实现使用@Provides告知 Dagger 如何提供你的项目所不具备的类只能在组件中声明一次模块根据注释的使用生命周期,为作用域注释命名,例如和依赖注入。

tmacfrank 2018

ZYQN7000系列VxWorks驱动开发:VxWorks系统移植

文章目录ZYQN7000驱动开发:VxWorks系统移植1.硬件环境2.编译vsb和vip工程2.1修改设备树文件2.2添加调试打印组件3.选择uboot来启动VxWorks内核4.尝试在开发板上启动内核4.1 拷贝镜像和设备树至SD卡4.2开发板上电4.2.1 uboot成功启动4.2.2 启动VxWorks5.添加shell和cmd组件 ZYQN7000驱动开发:VxWorks系统移植 1.硬件环境 正点原子领航者开发板 2.编译vsb和vip工程 vsb和vip工程的编译过程可以参考之前的文章,htt

明故宫的记忆 5504

Dagger1依赖注入

1.概述 Dagger作为工厂的替代品,声明依赖、指定如何满足以依赖、发布应用程序。通过构建标准的javax。基于JSR-330,方便每个类测试。您不需要一堆样板文件来将RpcCreditCardService替换为FakeCreditCardService。依赖注入不仅仅用于测试。它还使创建可重用、可互换的模块变得很容易。你可以在所有应用程序中共享相同的验证模块。您还可以在开发期间运行DevLo...

不是一枚开发 5万+

修改 Alist 密码时报错?看看这个坑怎么解决!

启动服务后,再修改密码”。以后再遇到类似问题,先检查服务是否正常运行,说不定就能少踩不少坑。如果还有其他 Alist 的问题,欢迎在评论区留言交流~

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1153

【LaTex】3.4 立体几何

本文介绍了使用LaTeX的tikz包绘制立体几何图形的两种方法。首先展示了基础立方体的绘制代码,通过定义8个顶点坐标并连接各边完成绘制。接着讲解了scope功能在3D绘图中的应用,包括标准平面(xy、xz、yz)的绘制方法,以及任意平面的定义技巧。重点说明了如何通过定义平面原点、x和y方向单位向量来创建旋转后的绘图平面,并以45°旋转的yz平面为例演示了圆的绘制。文章提供了完整的代码示例和对应的效果图示,展示了tikz在3D绘图中的灵活性和强大功能。

你的指尖有改变世界的力量 2452

Android之Dagger&Hilt依赖注入使用指南

Dagger2是一个依赖注入框架。它提供给Java和Android使用,主要用于模块间解耦、提高代码的健壮性和可维护性。使用了 IOC (控制反转)的思想,在编译阶段使用 APT 利用 Java 注解生成 Java 代码,然后结合部分手写代码来完整依赖注入工作。运行前需要先编译一次项目,目的是用 APT 生成中间代码。Dagger2不使用反射,在编译阶段生成代码,所以不会程序性能有影响。Dagger2 官网。

Android/Kotlin/Ktor/Compose 2528

05 SAP CPI 访问第一个CPI接口

其中的clientid的值可作为Basic验证的用户名,clientsecret的值可作为Basic验证的密码。点击SEND按钮,可看见返回状态为200 OK。在04中,我们得到TOKEN令牌。POSTMAN向下滚动。点击按钮获取token。

SAP CPI 661

Andriod Dagger2依赖注入

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

L_bsSua的博客 441

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

OV9734 DATASHEET,完整规格书

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

一文看懂依赖注入(Dagger2)

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

weixin_51020083的博客 983

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

使用Dagger 2进行依赖注入

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

wxx614817的专栏 535

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Dagger2 依赖注入的原理分析

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

okclouderx的博客 451

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

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

weixin_30877689的博客 368

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

上一篇文章Dagger2实现依赖注入之一步一步带你入门已经和大家分享了Dagger2的基本使用,如果你还没学会,可以边看文章边自己操作一遍。 上次说到,第六个步骤需要我们自己去重新编译一下项目,不然是无法执行最后一步的,也就是添加以下代码。 DaggerPassPortComponent.builder() .applicationCo

Interface_l的博客 746

dagger2 注入_Android依赖注入– Dagger 2

dagger2 注入In this tutorial, we’ll discuss and implement Dependency Injection (DI) in our android application. For those of you who have used DI in the past (possibly in Spring), the following section ...

从零开始的教程世界 579

用 Dagger 2 实现依赖注入

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

Treasure 287

依赖注入框架Dagger2详解(四),初级篇

什么是Dagger2 Dagger2是一种依赖注入的框架,能够在编译时自动生成出一些代码,这些代码可以帮助对应的实例初始化。 ,它是鼎鼎大名的Square公司旗下又一把利刃,还有一把黄油刀,叫做ButterKnife。 Dagger2起源于Dagger,是一款基于Java注解来实现的完全在编译阶段完成依赖注入的开源库,主要用于模块间解耦、提高代码的健壮性和可维护性。Dagger2在编译阶段通过ap...

门心叼龙的专栏 8375

依赖注入--Dagger2

一.什么是依赖注入,首先我认为是一种编程思想 简单来说,依赖注入就是为了控制反转和解耦的 当两个类或多个类 组合使用时,不可避免的会发生以下情况: public class MovieLister { private MovieFinder finder; public MovieLister() { finder = new MovieFinderImpl(); }

OutOfThinAir的博客 537

Dagger2依赖注入框架

Dagger2Dragger2是Android上的依赖注入框架, 是属于Dragger1的分支项目, 有Google开发维护, 而Dragger1是Square公司受到Google的轻量依赖注入框架Guice的启发创建的依赖注入框架. 后来Google收到Auto项目的启发开发了Dragger2, Auto就没必要介绍了官网: [https://github.com/google/dagger][h

肥宅 1063

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

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

2401_84009317的博客 830

dagger2 注入_使用Dagger 2在GWT中进行依赖注入

dagger2 注入 依赖注入是一种软件开发概念,其中为对象提供了创建所需的所有对象或值。 GWT用户已经熟悉GIN,但已经不推荐使用此工具,因此不再支持它,因此使用GIN的应用程序当前确实需要告别。 Dagger是GWT的新依赖注入框架。 对于那些不熟悉该框架的人,Dagger的目的是为Android提供DI,但现在已用于通用DI。 它也适用于GWT。 在本文中,我们将简要介绍Dagger,...

最佳 Java 编程 163
上一篇: 图解HashMap
下一篇: Android实现自动化打包:git+GitLab+蒲公英+钉钉机器人
missingcall
博客等级 码龄10年 8粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值