什么是IoC?

“依赖注入(DI)”有时候也被称为“控制反转(IoC)”本质上它们是同一个概念。具体是指,当某个类调用另外一个类的时候通常需要调用者来创建被调用者。但在控制反转的情况下调用者不在主动创建被调用者,而是改为由容器注入,因此而得名。这里的“创建”强调的是调用者的主动性。而依赖注入则不在需要调用者主动创建被调用者。举个例子通常情况下调用者(ClassA),会先创建好被调用者(FunBean),然后在调用方法callFoo中调用被调用者(FunBean)的foo方法:

  1. public class ClassA {
  2. private FunBean funBean = new FunBean();
  3. public void callFoo() {
  4. this.funBean.foo();
  5. }
  6. }
  7. public class FunBean {
  8. public void foo() {
  9. System.out.println("say ...");
  10. }
  11. }

使用了依赖注入的情况恰恰相反,调用者(ClassA)事先并不知道要创建哪个被调用 者(FunBean)。ClassA 调用的是被注入进来的 FunBean,通常我们会为需要依赖注入的 对象留有 set 方法,在调用 callFoo 方法之前是需要先将 funBean 对象通过 setFunBean 方法设置进来的。例如:

  1. public class ClassA {
  2. private FunBean funBean = null;
  3. public void setFunBean(FunBean funBean) {
  4. this.funBean = funBean;
  5. }
  6. public void callFoo() {
  7. this.funBean.foo();
  8. }
  9. }
  10. public class FunBean {
  11. ......
  12. }

严格意义上来说注入的形式分为两种,它们是“构造方法注入”和“set 属性注入”。我们经常听到有第三种注入方式叫“接口注入”。其实它只是“set 属性注入”的一种接口 表现形式。

  • 构造方法注入
    • 这种方式是指被注入的对象通过构造方法传入,例如下面代码:
  1. public class ClassA {
  2. private FunBean funBean = null;
  3. public ClassA(FunBean funBean) {
  4. this.funBean = funBean;
  5. }
  6. public void callFoo() {
  7. this.funBean.foo();
  8. }
  9. }

  • 属性注入
    • 是指被注入的对象通过其 get/set 读写属性方法注入进来,例如:
  1. public class ClassA {
  2. private FunBean funBean = null;
  3. public void setFunBean(FunBean funBean) {
  4. this.funBean = funBean;
  5. }
  6. public void callFoo() {
  7. this.funBean.foo();
  8. }
  9. }

  • 接口注入
    • 是指通过某个接口的 set 属性方法来注入,大家可以看到其本质还是 属性注入。只不过调用者(ClassA),需要实现某个注入接口。
  1. public interface IClassA {
  2. public void setFunBean(FunBean funBean);
  3. }
  4. public class ClassA implements IClassA {
  5. private FunBean funBean = null;
  6. public void setFunBean(FunBean funBean) {
  7. this.funBean = funBean;
  8. }
  9. public void callFoo() {
  10. this.funBean.foo();
  11. }
  12. }

上面我们讲解了什么是依赖注入,并且举例了一些依赖注入的表现形式。那么下一章我们来看看 Hasor 如何帮助我们你进行依赖注入。