什么是依赖注入?
- 就是目标类中所依赖的其他的类的初始化过程,不是通过手动编码的方式创建
- 不要在需要依赖的类中通过new来创建依赖而是通过方法提供的参数注入进来
常用四种依赖注入方式
- 常用方式,接口方法实现
interface ClassBInterface {
void setB(ClassBInterface b);
}
class ClassAInterface implements ClassBInterface {
ClassBInterface classB;
@Override
public void setB(ClassBInterface b) {
classB = b;
}
}
- set方式成员变量赋值
public class ClassAset{
ClassB classB;
public void setClassB(ClassB b){
classB = b;
}
}
- 构造器注入
public classAConstructor{
ClassB classB;
public ClassAConstructor(ClassB b){
classB = b;
}
}
- 注解方式,动态注入,FruitContainerInject不用关心Fruit具体实现
- 以dagger2为例,可以理解为Dagger2就是一个帮助我们写工厂代码的工具
public class FruitContainerInject{
@Inject
Fruit f;
public FruitContainerInject(){
}
}
@Inject注解
- 1 一个是标记在需要依赖的变量
public class Car{ @Inject Tyre tyre; public Car(){ DaggerCarComponent.builder().build().injectCar(this); } }
- 2 使用在构造函数上
public class Tyre{ @Inject public Tyre(){ } }
- 结论:
- 依赖注入是依赖的对象实例一>需要注入的实例属性
- 新建工厂实例并调用成员属性注入类完成Tyre的实例注入
@Component注解
- 可以标注接口或抽象类
- 可以完成依赖注入过程
@Component
public interface CarComponent{
void injectCar(Car car);
}
dagger2的inject和component注解实例和源码分析
我们想要将Student注入到College类,传统写法是这样的 ``` class OldCollege { Student student;
public OldCollege(Student student) {
this.student = student;
}
}
```
使用dagger2可以这样
- 首先将Student注入College
class College { @Inject Student student; public College() { DaggerCollegeComponent.builder().build().inject(this); } }
- 为了能够确定是哪个构造方法创建的Student实例,需要在需要的构造方法上加上@Inject注解
class Student { private int id; private String name; @Inject public Student() { System.out.println("Student create"); } public Student(int id, String name) { this.id = id; this.name = name; } }
- 现在College需要使用Student,为了链接这两个类,需要一个桥梁
@Component interface CollegeComponent { void inject(College college); }
原理分析
- 最终是通过工厂方法创建了Student实例
@Module和@Provides注解
@Injetc的问题:无法修改提供的类的构造函数,如jar包中的类,我们无法修改其源码
@Module可以给不能修改源码的类提供依赖,需要配合@Provides使用
- @Provide标注一个Module中的方法
- 步骤
- ①创建Module
- ②指明Component需要的Module
@Module public class CarModule { @Provides static Car provideCar(){ return new Car(); } } @Component(modules = CarModule.class) interface CarComponent { void injectCar(Car car); }
完整示例
- 这段代码中既有inject注解的构造方法,又有Provides提供的构造方法
- 最终实际上是根据注解生成了不同改造函数的Student实例
@Module
public class CollegeModule {
@Provides
ClassRoom provideClassRoom(){
return new ClassRoom();
}
@Provides
Student provideStudent(ClassRoom classRoom){
return new Student(classRoom);
}
}
@Component(modules = CollegeModule.class)
interface CollegeComponent {
void inject(College college);
}
class College {
@Inject
Student student;
public College() {
DaggerCollegeComponent
.builder()
.collegeModule(new CollegeModule())
.build()
.inject(this);
}
}
class Student {
private int id;
private String name;
private ClassRoom classRoom;
@Inject
public Student() {
System.out.println("Student create");
}
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public Student(ClassRoom classRoom) {
this.classRoom = classRoom;
}
}