dagger2官方GitHub: 點擊打開鏈接
這裏使用的是官方的實例分析的.
並稍微修改了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; //持有需要注入依賴對象的工廠
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相差甚遠.只想說一句寫註解解析類的纔是大神.