您的位置:首页 > 编程语言

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相差甚远.只想说一句写注解解析类的才是大神.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息