Dagger2的基础使用与原理

Dagger2的基础使用与原理

  • Dagger2的基础使用与原理
    • 前言
    • 基础使用
    • 实现原理

Dagger2的基础使用与原理

前言

Dagger 2 是基于 Java Specification Request(JSR) 330标准。利用 JSR 注解在编译时生成代码,来注入实例完成依赖注入

什么是依赖注入?
是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。

基础使用

1. Gradle配置

implementation 'com.google.dagger:dagger:2.27'
annotationProcessor 'com.google.dagger:dagger-compiler:2.27'

2.创建依赖对象(在这里也称为成员对象)与调用者

依赖对象

public class Chair {

    private String color;

    private String height;

    public Chair(String color, String height) {
        this.color = color;
        this.height = height;
    }

    public String getColor() {
        return color;
    }

    public String getHeight() {
        return height;
    }
}

调用者

/**
 * 1,创建Module(依赖对象库)  提供依赖的对象实例
 * 2,创建Component(连接依赖对象库与调用者的桥梁)
 * 3,使用@Inject在调用者中注入对象并绑定调用者
 */

public class HouseActivity extends Activity {
    @Inject
    Chair chair;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_house);
        //绑定component
        DaggerChairHouseComponent.create().injectHouse(this);

      
    }
}

3. 创建Module依赖对象库,作用:提供依赖对象的实例

/**
 * 提供属性注入对象的实例
 */
@Module
public class ChairCreatModule {

    /**
     * 提供属性(桌子)的生成
     * @return
     */
    @Provides
    public  Chair providesChair(){
        return new Chair("红色","1m");
    }

}

@Provides
  意思就是提供,显然在 Dagger2 中它的作用就是提供依赖。被标注函数的返回值既是依赖对象实例。
@Module
  模块,用 @Provides 注解的依赖必须存在一个用 @Module 注解的类中。@Module还可以包括其他module,如@Module(includes =xxx )
  
4. 创建Component桥梁,作用:连接调用者与Module依赖对象库的桥梁

/**
 * 连接器需要绑定Module,也可以绑定多个Module,同时也可以dependencies其他Component连接器
 */
@Component(modules = ChairCreatModule.class)
public interface ChairHouseComponent {

    /**
     * 连接器作为一个中间件,已经绑定依赖对象库了,那如何与调用者绑定呢?
     *
     * 通过提供一个方法
     * 1,返回值为void
     * 2,方法的参数为调用者对象(HouseActivity),不能是 HouseActivity 的父类或子类
     * 3,接口名任意
     * @param activity
     */

    void injectHouse(HouseActivity activity);

}

@Component
1,桥梁连接器, 连接调用者(HouseActivity)和依赖对象库(ChairCreateModule)的桥梁。
2,注意使用@Component标注,必要绑定module关联,同时也可以关联多个module.

连接器作为一个中间件,已经绑定依赖对象库了,那如何与调用者绑定呢?
是的,通过定义接口函数来绑定调用者

接口函数定义有哪些要求?
1,返回值为void
2,方法的参数为调用者对象(HouseActivity),不能是HouseActivity 的父类或子类
3,接口名任意

5. 调用接口函数绑定

 //绑定component 
 //方式一
 DaggerChairHouseComponent.create().injectHouse(this);
 //方式二
 DaggerChairHouseComponent.builder().chairCreatModule(new ChairCreatModule()).build().injectMain(this);

以上就是dagger简单的一个使用

实现原理

dagger在build时会在build/generated/source/apt产生3个文件,我们看下这3个文件。

ChairCreatModule_ProvidesChairFactory.java

// Generated by Dagger (https://dagger.dev).
package com.jet.daggertest.basic_use;

import dagger.internal.Factory;
import dagger.internal.Preconditions;

@SuppressWarnings({
    "unchecked",
    "rawtypes"
})
/**
 * 成员属性的工厂类
 * 主要是创建成员属性类对象
 */
public final class ChairCreatModule_ProvidesChairFactory implements Factory<Chair> {
  private final ChairCreatModule module;

  public ChairCreatModule_ProvidesChairFactory(ChairCreatModule module) {
    this.module = module;
  }

  @Override
  public Chair get() {
    return providesChair(module);
  }

  public static ChairCreatModule_ProvidesChairFactory create(ChairCreatModule module) {
    return new ChairCreatModule_ProvidesChairFactory(module);
  }

  public static Chair providesChair(ChairCreatModule instance) {
    return Preconditions.checkNotNull(instance.providesChair(), "Cannot return null from a non-@Nullable @Provides method");
  }
}

可以看出,这是一个工厂类,通过提供get()方法向外提供依赖对象实例。结论是该工厂类主要是创建成员属性类对象。

HouseActivity_MembersInjector.java

// Generated by Dagger (https://dagger.dev).
package com.jet.daggertest.basic_use;

import dagger.MembersInjector;
import dagger.internal.InjectedFieldSignature;
import javax.inject.Provider;

@SuppressWarnings({
    "unchecked",
    "rawtypes"
})
/**
 * 成员属性注入类
 * 主要工作是获得调用者并初始化被@Inject标注的成员
 */
public final class HouseActivity_MembersInjector implements MembersInjector<HouseActivity> {
  //
  private final Provider<Chair> chairProvider;

  public HouseActivity_MembersInjector(Provider<Chair> chairProvider) {
    this.chairProvider = chairProvider;
  }

  public static MembersInjector<HouseActivity> create(Provider<Chair> chairProvider) {
    return new HouseActivity_MembersInjector(chairProvider);}

  @Override
  public void injectMembers(HouseActivity instance) {
    //获得调用者,并设置赋予调用者中被@Inject标注的成员属性对象
    injectChair(instance, chairProvider.get());
  }

  @InjectedFieldSignature("com.jet.daggertest.basic_use.HouseActivity.chair")
  public static void injectChair(HouseActivity instance, Chair chair) {
    //赋予调用者中被@Inject标注的成员属性对象
    instance.chair = chair;
  }
}

可以看出injectChair(HouseActivity instance, Chair chair)是一个注入依赖对象的方法,赋予调用者中被@Inject标注的成员属性对象实例。结果:这是一个成员属性注入类。

对象注入类与依赖对象都有了,接下来就是如何把他们关联起来,这就是component的操作了。

DaggerChairHouseComponent.java

// Generated by Dagger (https://dagger.dev).
package com.jet.daggertest.basic_use;

import dagger.internal.Preconditions;

@SuppressWarnings({
    "unchecked",
    "rawtypes"
})
public final class DaggerChairHouseComponent implements ChairHouseComponent {
  private final ChairCreatModule chairCreatModule;

  private DaggerChairHouseComponent(ChairCreatModule chairCreatModuleParam) {
    this.chairCreatModule = chairCreatModuleParam;
  }

  public static Builder builder() {
    return new Builder();
  }

  public static ChairHouseComponent create() {
    return new Builder().build();
  }

  @Override
  public void injectHouse(HouseActivity activity) {
    injectHouseActivity(activity);}

  /**
   * 作为桥接成员属性注入类(HouseActivity_MembersInjector)与成员属性工厂类(ChairCreatModule_ProvidesChairFactory)
   * @param instance
   * @return
   */
  private HouseActivity injectHouseActivity(HouseActivity instance) {
    //获取调用者
    //并通过成员属性的工厂类获得成员对象
    //最后调用成员属性注入类完成注入
    HouseActivity_MembersInjector.injectChair(instance, ChairCreatModule_ProvidesChairFactory.providesChair(chairCreatModule));
    return instance;
  }

  public static final class Builder {
    private ChairCreatModule chairCreatModule;

    private Builder() {
    }

    public Builder chairCreatModule(ChairCreatModule chairCreatModule) {
      this.chairCreatModule = Preconditions.checkNotNull(chairCreatModule);
      return this;
    }

    public ChairHouseComponent build() {
      if (chairCreatModule == null) {
        this.chairCreatModule = new ChairCreatModule();
      }
      return new DaggerChairHouseComponent(chairCreatModule);
    }
  }
}

我们看下HouseActivity_MembersInjector.injectChair(instance, ChairCreatModule_ProvidesChairFactory.providesChair(chairCreatModule)); 这个方法,获取调用者,并通过成员属性的工厂类获得成员对象,最后调用成员属性注入类完成注入。

粗糙的描绘了一下图片:
Dagger2的基础使用与原理_第1张图片

结论:
1,成员属性注入类(HouseActivity_MembersInjector):负责将成员属性chair对象赋予调用者中以@Inject标注的对象给予初始化。
2,成员属性工厂类(ChairCreatModule_ProvidesChairFactory):负责生产成员属性chair对象。
3,桥梁(DaggerChairHouseComponent):通过成员属性工厂类(ChairCreatModule_ProvidesChairFactory)获得成员对象,并调用成员属性注入类(HouseActivity_MembersInjector)
的方法HouseActivity_MembersInjector.injectChair(HouseActivity instance, Chair chair)给调用者注入成员对象。

你可能感兴趣的:(dagger2,dagger,java)