25

依赖注入似乎是件好事。一般来说,依赖关系应该注入到需要它们的方法中,还是应该注入到类的构造函数中?

请参阅下面的示例以演示注入相同依赖项的两种方法。

//Inject the dependency into the methods that require ImportantClass
Class Something {

    public Something()
    {
         //empty
    }

    public void A() 
    {
         //do something without x
    }

    public void B(ImportantClass x)
    {
         //do something with x
    }

    public void C(ImportantClass x)
    {
         //do something with x
    }
}

//Inject the dependency into the constructor once
Class Something {
    private ImportantClass _x
    public Something(ImportantClass x)
    {
         this._x = x;
    }

    public void A() 
    {
         //do something without x
    }

    public void B()
    {
         //do something with this._x
    }

    public void C()
    {
         //do something with this._x
    }

}
4

5 回答 5

17

构造函数注入的主要好处是它允许将您的字段标记为最终字段。例如:

class Foo {
    private final Bar _bar;

    Foo(Bar bar) {
        _bar=bar;
    }
}

以下页面列出了优缺点:Guice 最佳实践

方法注入

  • + 不是现场注入
  • + 唯一适用于一些奇怪的边缘情况的东西

构造函数注入

  • + 字段可以是最终的!
  • + 注射不可能被跳过
  • + 一目了然的依赖关系
  • + 这就是建筑理念的全部意义所在
  • - 没有可选的注射
  • - 当 DI 库不能自己实例化时无用
  • - 子类需要“了解”其超类所需的注入
  • - 对于只“关心”其中一个参数的测试不太方便
于 2008-10-17T18:59:05.700 回答
3

通过不在每个方法中注入依赖项,您可以强制每个调用者知道或检索依赖项。

同样从工具的角度来看,有许多可用的框架(至少在 .NET 中)可以启用或使构造函数注入更容易执行。这不应影响决定,但会使其更具吸引力。

祝你好运。

于 2008-10-17T19:02:02.543 回答
3

如果您在方法期间注入,那么您不会将行为抽象与具体依赖项区分开来。这是一个很大的禁忌:)。您希望依赖抽象,因此您不会与类依赖项的依赖项耦合。. .

由于您的构造函数不会存在于您的具体类支持的任何接口中,而不是您没有耦合到该依赖项。但是方法调用会有这个问题。

这是一篇关于这个主题的好文章:

http://chrisdonnan.com/blog/2007/05/20/conquest-through-extreme-composition-glue-part-2/

于 2008-10-26T23:14:31.353 回答
2

另一种方法是使用依赖项的设置器。有时这与构造函数注入结合使用。如果您想更改稍后使用的实现而不需要重新创建实例,这将很有用。

public interface IFoo
{
   void Do();
}

public class DefaultFoo : IFoo
{
   public void Do()
   {
   }
}

public class UsesFoo
{
   private IFoo foo;
   public IFoo Foo
   {
       set { this.foo = value; }
   }

   public UsesFoo()
   {
      this.Foo = new DefaultFoo();
   }

   public UsesFoo( IFoo foo )
   {
      this.Foo = foo;
   }

   public void DoFoo()
   {
      this.Foo.Do();
   }
}
于 2008-10-17T19:25:35.523 回答
0

Crazy Bob Lee说尽可能使用构造函数注入。仅当您无法控制实例化(例如在 servlet 中)时才使用方法注入。

于 2008-10-17T19:02:05.803 回答