Dagger2 原理分析
来源:互联网 发布:软件如何推广 编辑:程序博客网 时间:2024/06/05 23:07
最近在找实习工作,复习到这一个知识点,记录下。
Dagger2 使用编译时注解 + APT 实现依赖注入,能带来什么好处呢?一个词:解耦。在项目越来越庞大的时候,Dagger2 就体现出强大之处了。
编译时注解 + APT 实现的框架,通过解析注解,然后生成辅助类。But,是没用到反射的。都是在编译时完成。要分析 Dagger2 的工作原理,那么就要去探索生成的辅助类。
一个简单的例子,往 MainActivity 注入 MainPresenter 依赖(ps:MVP + Dagger2 简直不能太般配):
public class MainActivity extends AppCompatActivity { public static final String TAG = MainActivity.class.getSimpleName(); @Inject MainPresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); injectDependences(); Log.d(TAG,"MainPresenter ->" + presenter.hashCode()); } private void injectDependences(){ DaggerMainComponent.builder() .mainModule(new MainModule()) .build() .inject(this); }}
@Component(modules = {MainModule.class})public interface MainComponent { void inject(MainActivity mainActivity);}
@Modulepublic class MainModule { @Provides MainPresenter provideMainPresenter(){ return new MainPresenter(); }}
public class MainPresenter {}
以上代码直接贴了,很简单。接下来我们分析在编译时生成的类。这些类存放在在 app/build/generated/source/apt/debug/包名
DaggerMainComponent 源码如下所示:
@Generated("dagger.internal.codegen.ComponentProcessor")public final class DaggerMainComponent implements MainComponent { private Provider<MainPresenter> provideMainPresenterProvider; private MembersInjector<MainActivity> mainActivityMembersInjector; private DaggerMainComponent(Builder builder) { assert builder != null; initialize(builder); } public static Builder builder() { return new Builder(); } public static MainComponent create() { return builder().build(); } private void initialize(final Builder builder) { this.provideMainPresenterProvider = MainModule_ProvideMainPresenterFactory.create(builder.mainModule); this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideMainPresenterProvider); } //inject 方法实现依赖注入 @Override public void inject(MainActivity mainActivity) { mainActivityMembersInjector.injectMembers(mainActivity); } public static final class Builder { private MainModule mainModule; private Builder() { } public MainComponent build() { if (mainModule == null) { this.mainModule = new MainModule(); } return new DaggerMainComponent(this); } public Builder mainModule(MainModule mainModule) { if (mainModule == null) { throw new NullPointerException("mainModule"); } this.mainModule = mainModule; return this; } }}
DaggerMainComponent 是使用建造者模式创建的,那么先看到其内部的 Builder 类,Builder 类有一个 mainModule 方法,传入 MainModule 对象,如果 MainModule 为空会抛出空指针异常,最后 mainModule 方法返回了 this。
然后调用 build 方法。在 build 方法中创建一个 DaggerMainComponent 并返回,此时只需要关注 DaggerMainComponent 的构造方法即可。
在 DaggerMainComponent 的构造方法中,将 Builder 对象传入 initialize 方法,initialize 方法虽然只有两行代码,但这两行代码很关键。我们看到这个 initialize 方法做了两件事。
- 调用了 MainModule_ProvideMainPresenterFactory 类的静态方法 create,并将 MainModule 对象传入,返回了一个 Provider 对象。
这里的 MainModule 对象来自 Builder 对象。是在初始化 DaggerMainComponent 的时候创建的。 - 调用 MainActivity_MembersInjector 的 create,并将 Provider 对象传进。返回一个 MembersInjector 对象。
到这里,只需要记住。Apt 在编译时为我们生成了三个类
- DaggerMainComponent
- MainModule_ProvideMainPresenterFactory
- MainActivity_MembersInjector
虽然名字很长,但是认真看几遍的话,很还记的。
以上是 DaggerMainComponent 类,还需要继续挖掘 MainModule_ProvideMainPresenterFactory 和 MainActivity_MembersInjector。
MainModule_ProvideMainPresenterFactory 源码如下:
@Generated("dagger.internal.codegen.ComponentProcessor")public final class MainModule_ProvideMainPresenterFactory implements Factory<MainPresenter> { private final MainModule module; public MainModule_ProvideMainPresenterFactory(MainModule module) { assert module != null; this.module = module; } @Override public MainPresenter get() { MainPresenter provided = module.provideMainPresenter(); if (provided == null) { throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method"); } return provided; } public static Factory<MainPresenter> create(MainModule module) { return new MainModule_ProvideMainPresenterFactory(module); }}
我们在 DaggerMainComponent 中调用了 MainModule_ProvideMainPresenterFactory 类的静态方法 create。那么从调用入口开始分析,找到 create 方法。create 方法内部 new 了一个 MainModule_ProvideMainPresenterFactory 对象。注意到还有一个 get 方法,但是我们现在还不知道在哪里调用了这个 get 方法。先记下。
MainActivity_MembersInjector 源码如下:
@Generated("dagger.internal.codegen.ComponentProcessor")public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> { private final MembersInjector<AppCompatActivity> supertypeInjector; private final Provider<MainPresenter> presenterProvider; public MainActivity_MembersInjector(MembersInjector<AppCompatActivity> supertypeInjector, Provider<MainPresenter> presenterProvider) { assert supertypeInjector != null; this.supertypeInjector = supertypeInjector; assert presenterProvider != null; this.presenterProvider = presenterProvider; } @Override public void injectMembers(MainActivity instance) { if (instance == null) { throw new NullPointerException("Cannot inject members into a null reference"); } supertypeInjector.injectMembers(instance); instance.presenter = presenterProvider.get(); } public static MembersInjector<MainActivity> create(MembersInjector<AppCompatActivity> supertypeInjector, Provider<MainPresenter> presenterProvider) { return new MainActivity_MembersInjector(supertypeInjector, presenterProvider); }}
同样是从调用入口 create 方法开始。生成 MainActivity_MembersInjector 对象。
到这里为止,初始化工作全部完成。
现在想一下 MainPresenter 是怎样注入到 MainActivity 的呢?
DaggerMainComponent.builder() .mainModule(new MainModule()) .build() .inject(this);
很容易猜想到是 DaggerMainComponent 的 inject 方法。
我们回到 DaggerMainComponent 从入口 inject 方法开始, inject 方法传进了MainActivity。然后调用了 MainActivityMembersInjector 对象的 injectMembers 方法,如下所示:
@Overridepublic void injectMembers(MainActivity instance) { if (instance == null) { throw new NullPointerException("Cannot inject members into a null reference"); } supertypeInjector.injectMembers(instance); instance.presenter = presenterProvider.get();}
而在 injectMembers 方法,终于可以看到调用 get 方法的代码
instance.presenter = presenterProvider.get();
就这样完成了依赖注入,instance 是 MainActivity,而 presenter 是需要注入的 MainPresenter 对象。
那么现在只需要关注 presenterProvider 的 get 方法即可。presenterProvider 是什么?
是 MainModule_ProvideMainPresenterFactory 对象,在创建 MainActivity_MembersInjector 的时候传入的。
找到 MainModule_ProvideMainPresenterFactory 的 get 方法。如下所示:
@Overridepublic MainPresenter get() { MainPresenter provided = module.provideMainPresenter(); if (provided == null) { throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method"); } return provided;}
其内部是调用了 MainModule 对象的工厂方法 provideMainPresenter 方法来生成 MainPresenter 对象。如下:
@Modulepublic class MainModule { @Provides MainPresenter provideMainPresenter(){ return new MainPresenter(); }}
分析完毕!
总结
DaggerMainComponent 在创建的时候,需要传入 Module,这个传入的 Module 到底用来干嘛的? Factory 的 get 方法中会调用 Mudule 的工厂方法获取到依赖。
DaggerMainComponent 在创建的时候,还创建了 Factory(工厂类,对应上文的 MainModule_ProvideMainPresenterFactory) 和 MembersInjector(成员注入类,对应上文的 MainActivity_MembersInjector) 。
当 DaggerMainComponent 调用 inject 方法注入依赖的时候,会调用 MembersInjector 的 injectMembers 方法,在 injectMembers 方法中会调用Factory 的 get 方法获取到依赖(get 方法中实际会调用 Mudule 的工厂方法获取到依赖),最后将依赖赋值给 目标类 的成员变量。完成依赖注入。
最后,你会发现这篇文章没有使用到 @Qulifier, @Scope(我觉的@Scope注解不好理解)。而且Module类也只有一个方法,如果有多个方法呢?生成的辅助类又会如何?
学习资料:
https://google.github.io/dagger/
神兵利器Dagger2
Android:dagger2让你爱不释手-基础依赖注入框架篇
- Dagger2 原理分析
- Dagger2注入原理简单分析
- Dagger2详解-从代码分析其原理
- Dagger2详解(原理)
- Dagger2注入原理
- Dagger2 使用+原理解析
- Dagger2依赖关系分析
- Dagger2代码分析
- Dagger2分析学习
- Dagger2基本使用与原理
- Dagger2
- Dagger2
- Dagger2
- Dagger2
- dagger2
- Dagger2
- Dagger2
- Dagger2
- 160. Intersection of Two Linked Lists
- 白话经典算法系列之六 快速排序 快速搞定
- 动态改变actionbar的menu菜单MenuItem的显示--binbinyang
- Source Insight中集成Uncrustify格式化代码
- 剑指Offer23 : 从上而下打印二叉树--层序遍历
- Dagger2 原理分析
- shell-遍历文件/目录
- Mysql 5.7 开启远程连接
- BZOJ 3289 Mato的文件管理
- 关于高德地图定位跑到非洲的情况。
- MySQL函数if(expr1,expr2,expr3)
- Markdown 编辑器
- 在Android 5.0中使用JobScheduler
- 虚拟机和真机之间的细微差别