Wednesday, April 20, 2016

Dagger



Dagger is a fully static, compile-time dependency injection framework

https://medium.com/square-corner-blog/keeping-the-daggers-sharp-%EF%B8%8F-230b3191c3f
Favor constructor injection over field injection
Field injection requires the fields to be non final and non private.

Forgetting an @Inject on a field introduces a NullPointerException.
Constructor injection is better because it allows for immutable and therefore thread safe objects that don’t have a partially constructed state.


  @Inject public CardConverter(PublicKeyManager publicKeyManager) {
    this.publicKeyManager = publicKeyManager;
  }


https://github.com/google/dagger
http://blog.zhaiyifan.cn/2016/03/27/android-new-project-from-0-p4/
关于Dagger2的最初想法,来自于2013年12月的Proposal: Dagger 2.0,Jake大神在issue里面也有回复哦,而idea的来源者Gregory Kick的GitHub个人主页也没多少follower,自己也没几个项目,主要都在贡献其他的repository,可见海外重复造轮子的风气比我们这儿好多了。
扯远了,Dagger2的诞生就是源于开发者们对Dagger1半静态化半运行时的不满(尤其是在服务端的大型应用上),想要改造成完整的静态依赖图生成,完全的代码生成式依赖注入解决方案。在权衡了什么对Android更适合,以及对大型应用来说什么更有意义(往往有可怕数量的注入)两者后,Dagger2诞生了。
是通过依赖注入让你少些很多公式化代码,更容易测试,降低耦合,创建可复用可互换的模块。你可以在Debug包,测试运行包以及release包优雅注入三种不同的实现。

但问题在于,在大型应用中,把这些依赖全都分离,然后自己去创建的话,会是一个很大的工作量——毫无营养的公式化代码,一堆Factory类。不仅仅是工作量的问题,这些依赖可能还有顺序的问题,A依赖B,B依赖C,B依赖D,如此一来C、D就必须在A、B的后面,手动去做这些工作简直是一个噩梦 =。=(哈哈,是不是想到了appliation初始化那些依赖)。Google的工程师碰到的问题就是在Android上有3000行这样的代码,而在服务器上的大型程序则是100000行。
Guice虽然较Spring进了一步,干掉了xml,通过Java声明依赖注入比起Spring好找多了,但其跟踪和报错(运行时的图验证)实在令人抓狂,而且在不同环境注入不同实例的配置也挺恶心的(if else各种判断),感兴趣的可以去看看,项目就在GitHub上,Android版本的叫RoboGuice。
而Dagger2和Dagger1的差别在上节已经提到了,更专注于开发者的体验,从半静态变为完全静态,从Map式的API变成申明式API(@Module),生成的代码更优雅,更高的性能(跟手写一样),更简单的debug跟踪,所有的报错也都是在编译时发生的。
@Component(modules = DripCoffeModule.class)
interface CoffeeMakerComponet {
CoffeeMaker getCoffeeMaker();
}

// 会生成这样的代码,Dagger_CoffeeMakerComponent里面就是一堆Provider,
// 或者是单例,或者是通过DripCoffeeModule申明new的方式,开发者不必关心依赖顺序
CoffeeMakerComponent component = Dagger_CoffeeMakerComponent.create();
CoffeeMaker coffeeMaker = component.getCoffeeMaker();

Dagger2的Scope,除了Singleton(root),其他都是自定义的,无论你给它命名PerActivity、PerFragment,其实都只是一个命名而已,真正起作用的是inject的位置,以及dependency。
Scope起的更多是一个限制作用,比如不同层级的Component需要有不同的scope,注入PerActivity scope的component后activity就不能通过@Inject去获得SingleTon的实例,需要从application去暴露接口获得(getAppliationComponent获得component实例然后访问,比如全局的navigator)。
当然,另一方面则是可读性和方便理解,通过scope的不同很容易能辨明2个实例的作用域的区别。


Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts