dagger2的生成源码简单分析
2017-11-27 15:14
260 查看
dagger2官方GitHub: 点击打开链接
直接上图,自己对dagger2构架的见解:这里使用的是官方的实例分析的.
并稍微修改了CoffeeApp
@Singleton @Component(modules = {DripCoffeeModule.class}) public interface CoffeeApp { void inject(App coffeeApp); CoffeeMaker maker(); }
然后生成 :
CoffeeApp会被编译器生成如下代码:
public final class DaggerCoffeeApp implements CoffeeApp { private Provider<Heater> provideHeaterProvider; private Provider<Thermosiphon> thermosiphonProvider; //持有各个提供者 private Provider<Pump> providePumpProvider; private Provider<CoffeeMaker> provideMakerProvider; private DaggerCoffeeApp(Builder builder) { assert builder != null; initialize(builder); //在这里对提供者或者对类注入器初始化 } public static Builder builder() { return new Builder(); } public static CoffeeApp create() { return builder().build(); } @SuppressWarnings("unchecked") private void initialize(final Builder builder) { this.provideHeaterProvider = DoubleCheck.provider( DripCoffeeModule_ProvideHeaterFactory.create(builder.dripCoffeeModule)); this.thermosiphonProvider = Thermosiphon_Factory.create(provideHeaterProvider); this.providePumpProvider = (Provider) thermosiphonProvider; this.provideMakerProvider = DripCoffeeModule_ProvideMakerFactory.create( builder.dripCoffeeModule, provideHeaterProvider, providePumpProvider); } @Override public void inject(App coffeeApp) { //空实现,类似空指针模式. MembersInjectors.<App>noOp().injectMembers(coffeeApp); } @Override public CoffeeMaker maker() { return provideMakerProvider.get(); } //构建component需要的参数 public static final class Builder { private DripCoffeeModule dripCoffeeModule; private Builder() {} public CoffeeApp build() { //看看这里就知道你可以传递module也可以不传了吧 if (dripCoffeeModule == null) { this.dripCoffeeModule = new DripCoffeeModule(); } return new DaggerCoffeeApp(this); } public Builder dripCoffeeModule(DripCoffeeModule dripCoffeeModule) { this.dripCoffeeModule = Preconditions.checkNotNull(dripCoffeeModule); return this; } } }
这DaggerCoffeeApp的作用:对module,提供者和类注入器(现在还没有)进行初始化,也是一个交互的场所.
然后根据module 提供的实例的方法生成 DripCoffeeModule_ProvideHeaterFactory,DripCoffeeModule_ProvideMakerFactory类,上面的xxx_mmmFactory就是指这样的了,而通过@inject构造注入将生成类名_Factory工厂类:Thermosiphon_Factory
,Person_Factory.
DripCoffeeModule_ProvideHeaterFactory 代码如下:
public final class DripCoffeeModule_ProvideHeaterFactory implements Factory<Heater> {
private final DripCoffeeModule module;
//这里是通过module来提供实例,所以将持有module实例
public DripCoffeeModule_ProvideHeaterFactory(DripCoffeeModule module) {
assert module != null;
this.module = module;
}
@Override
public Heater get() {
//看到没有,会调用module的方法,但是provideHeater最终还是调用new 对象()...所以建议使用@inject构造比他效率高
return Preconditions.checkNotNull(
module.provideHeater(), "Cannot return null from a non-@Nullable @Provides method");
}
public static Factory<Heater> create(DripCoffeeModule module) {
return new DripCoffeeModule_ProvideHeaterFactory(module);
}
Thermosiphon_Factory 代码如下:
public final class Thermosiphon_Factory implements Factory<Thermosiphon> {
private final Provider<Heater> heaterProvider;
public Thermosiphon_Factory(Provider<Heater> heaterProvider) {
assert heaterProvider != null;
this.heaterProvider = heaterProvider;
}
@Override
public Thermosiphon get() {
//看到没有,@inject注入直接调用new 对象();
return new Thermosiphon(heaterProvider.get());
}
public static Factory<Thermosiphon> create(Provider<Heater> heaterProvider) {
return new Thermosiphon_Factory(heaterProvider);
}
/** Proxies {@link Thermosiphon#Thermosiphon(Heater)}. */
public static Thermosiphon newThermosiphon(Object heater) {
return new Thermosiphon((Heater) heater);
}
}
其他的工厂类都是一样的,都是创建对象和提供对应对象作用.很简单的类
既然对象工厂有,交互环境也有了,类注入器呢,如何注入呢.但是上面的代码只知道App 这个类需要注入依赖...,所以只是给
出了MembersInjectors.<App>noOp().injectMembers(coffeeApp),空实现.那么现在注入代码如下;
public class App extends Application {
@Inject
CoffeeMaker coffeeMaker;
@Inject
Heater heater; //被@inject修饰的对象需要注入依赖
@Inject
Teacher teacher;
@Inject
Person person;
private static final String TAG = "App";
@Override
public void onCreate() {
super.onCreate();
CoffeeApp build = DaggerCoffeeApp.builder().build();//构建component对象
build.inject(this); //注入
CoffeeMaker coffeeMaker1=coffeeMaker;
Heater heater1=heater;
CoffeeApp build3 = DaggerCoffeeApp.builder().build();
build3.inject(this); //注入
CoffeeMaker coffeeMaker2=coffeeMaker;
Heater heater2=heater;
Log.e(TAG, "onCreate: "+(coffeeMaker2==coffeeMaker1 ));
Log.e(TAG, "onCreate: "+(heater2==heater1 )); //这个是被@Singleton修饰的,但是结果是false.所谓的单例是
指在这个component实例中只会调用new 对象()方法一次,在这个component实例中我是单例的.但是上面我创建两个component.所以不等
}
public CoffeeMaker getCoffeeMaker(){
return coffeeMaker;
}
}
然后重新编译:
App这个类的注入器已经生成了,代码如下:
生成代码如下:
public final class App_MembersInjector implements MembersInjector<App> {
private final Provider<CoffeeMaker> coffeeMakerProvider;
private final Provider<Heater> heaterProvider;
private final Provider<Teacher> teacherProvider; //持有需要注
cf60
入依赖对象的工厂
private final Provider<Person> personProvider;
//类初始化传递工厂
public App_MembersInjector(
Provider<CoffeeMaker> coffeeMakerProvider,
Provider<Heater> heaterProvider,
Provider<Teacher> teacherProvider,
Provider<Person> personProvider) {
assert coffeeMakerProvider != null;
this.coffeeMakerProvider = coffeeMakerProvider;
assert heaterProvider != null;
this.heaterProvider = heaterProvider;
assert teacherProvider != null;
this.teacherProvider = teacherProvider;
assert personProvider != null;
this.personProvider = personProvider;
}
public static MembersInjector<App> create(
Provider<CoffeeMaker> coffeeMakerProvider,
Provider<Heater> heaterProvider,
Provider<Teacher> teacherProvider,
Provider<Person> personProvider) {
return new App_MembersInjector(
coffeeMakerProvider, heaterProvider, teacherProvider, personProvider);
}
@Override
public void injectMembers(App instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
//重点在这里....通过..App的实例访问属性,并通过工厂.get(),方法对属性赋值
instance.coffeeMaker = coffeeMakerProvider.get();
instance.heater = heaterProvider.get();
instance.teacher = teacherProvider.get();
instance.person = personProvider.get();
}
//以下的方法可以直接访问,但是如果直接访问我要你这个dagger框架何用,又如何优雅的解决注入问题呢
public static void injectCoffeeMaker(App instance, Provider<CoffeeMaker> coffeeMakerProvider) {
instance.coffeeMaker = coffeeMakerProvider.get();
}
public static void injectHeater(App instance, Provider<Heater> heaterProvider) {
instance.heater = heaterProvider.get();
}
public static void injectTeacher(App instance, Provider<Teacher> teacherProvider) {
instance.teacher = teacherProvider.get();
}
public static void injectPerson(App instance, Provider<Person> personProvider) {
instance.person = personProvider.get();
}
}
上面的代码已经得知注入是在injectMembers()方法中的,那它是在什么地方调用的呢.别忘了外观类.发生改变如下:
public final class DaggerCoffeeApp implements CoffeeApp { private Provider<Heater> provideHeaterProvider; private Provider<Thermosiphon> thermosiphonProvider; private Provider<Pump> providePumpProvider; private Provider<CoffeeMaker> provideMakerProvider; private MembersInjector<App> appMembersInjector; //增加类注入器 private DaggerCoffeeApp(Builder builder) { assert builder != null; initialize(builder); } public static Builder builder() { return new Builder(); } public static CoffeeApp create() { return builder().build(); } @SuppressWarnings("unchecked") private void initialize(final Builder builder) { this.provideHeaterProvider = DoubleCheck.provider( DripCoffeeModule_ProvideHeaterFactory.create(builder.dripCoffeeModule)); this.thermosiphonProvider = Thermosiphon_Factory.create(provideHeaterProvider); this.providePumpProvider = (Provider) thermosiphonProvider; this.provideMakerProvider = DripCoffeeModule_ProvideMakerFactory.create( builder.dripCoffeeModule, provideHeaterProvider, providePumpProvider); this.appMembersInjector = App_MembersInjector.create( // 增加了类注入器的初始化 provideMakerProvider, provideHeaterProvider, Teacher_Factory.create(), Person_Factory.create()); } @Override public void inject(App coffeeApp) { appMembersInjector.injectMembers(coffeeApp); //当调用这个方法时才真正的注入,前期的工作要做好.不然报错. 实现就是 //上面的啦. } @Override public CoffeeMaker maker() { return provideMakerProvider.get(); } public static final class Builder { private DripCoffeeModule dripCoffeeModule; private Builder() {} public CoffeeApp build() { if (dripCoffeeModule == null) { this.dripCoffeeModule = new DripCoffeeModule(); } return new DaggerCoffeeApp(this); } public Builder dripCoffeeModule(DripCoffeeModule dripCoffeeModule) { this.dripCoffeeModule = Preconditions.checkNotNull(dripCoffeeModule); return this; } }
然后在客户端调用:
CoffeeApp build = DaggerCoffeeApp.builder().build(); build.inject(this);
的确是优雅.简单.但是中间生成了几个类:component接口和实现,module ,factory,注入器为创建对象总共生成了五个类,如果只有
@inject构造注入至少4个类,而创建对象我只需要new 对象()就ok了...需要那么麻烦吗,真是令人深思的问题.
ps:以上是对dagger源码简单解析...不对地方多指教.类注入器是自己起的,你们随便叫.......真的跟spring相差甚远.只想说一句写注解解析类的才是大神.
相关文章推荐
- Retrofit 源码简单分析
- adb 深入分析一1、adb模块的源码路径,源码编译生成的结果。 2、adb模块分为adb client、adb server、services、adbd daemon几个模块。 3、adb通讯模
- 各类建站源码简单分析
- iText生成PDF的关键源码分析
- asp生成和导出excel和word数据源码和代码,简单好用(已经测试可以用)
- ButterKnife源码分析及简单实现
- spring4.0 源码分析 搭建简单的分析环境(一)
- SpringIOC的源码简单分析 eclipseIDE debug
- (转)网上流传的天龙源码框架分析之一 --- 客户端简单介绍
- 由简单的LED驱动分析内核源码包中的s3c2410寄存器宏定
- 一个简单的python代理服务器源码分析
- rstplib源码分析---快速生成树之时间信息
- Android--谷歌MVP代码分析<简单源码>
- MyBatis 源码分析——生成Statement接口实例
- Context简单说明(源码分析)
- Spark组件之GraphX学习5--随机图生成和消息发送aggregateMessages以及mapreduce操作(含源码分析)
- Mangos源码分析(3):服务器结构探讨之简单的世界服实现
- SpringCloud 笔记 (四)---- 简单源码分析
- 简单分析Android中添加shortcut方面的源码
- @Html.AntiForgeryToken() 源码分析,表单防伪码的生成