什么是依赖注入和Spring框架?

Eug*_*neP 14 java spring dependency-injection

可能重复:
什么是依赖注入?
春天究竟是什么?

我想知道 Spring Framework是什么?为什么以及何时应该在Java Enterprise开发中使用它? 答案是"依赖注入框架".好吧,使用依赖注入框架时我们有什么优势?用setter值和/或构造函数参数描述类的想法对我来说似乎很奇怪.为什么这样?因为我们可以在不重新编译项目的情况下更改属性?这就是我们获得的一切吗?

那么,我们应该在beans.xml中描述哪些对象?所有对象还是只有几个?

最简单的答案是受欢迎的

Mar*_*ann 23

我们使用依赖注入(DI)来实现松散耦合.选择任何特定的DI容器并不重要.

每次使用new关键字创建类的实例时,都会将代码紧密地耦合到该类,并且您将无法用不同的实现替换该特定实现(至少在没有重新编译代码的情况下).

这在C#中看起来像这样(但在Java中是等效的):

public class MyClass
{
    public string GetMessage(int key)
    {
        return new MessageService().GetMessage(key)
    }
}
Run Code Online (Sandbox Code Playgroud)

这意味着如果您以后想要使用不同的MessageService,则不能.

另一方面,如果您将一个接口注入到类中并遵循Liskov Substition Principle,您将能够独立地改变使用者和服务.

public class MyClass
{
    private readonly IMessageService messageService;

    public MyClass(IMessageService messageService)
    {
        if(messageService == null)
        {
            throw new ArgumentNullException("messageService");
        }

        this.messageService = messageService;
    }

    public string GetMessage(int key)
    {
        return this.messageService.GetMessage(key)
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然这看起来更复杂,但我们现在已经设法遵循单一责任原则,确保每个协作者只做一件事,并且我们可以彼此独立地改变.

此外,我们现在可以在不改变类本身的情况下改变MyClass的行为,从而坚持开放/封闭原则.


Pab*_*dez 12

重新配置被高估了.使用DI最重要的是可测试性.由于您的类不依赖于实现,而是依赖于抽象,您可以在单元测试中用模拟/存根替换它们.

没有DI:

class SaleAction{

 private BillingService billingService;

 public SaleAction(){
   billingService = new CreditCardService(); //dependency is hardcoded
 }

 public void pay(long amount){
   //pre payment logic
   billingService.pay(amount);
   //post payment logic
 }

}
Run Code Online (Sandbox Code Playgroud)

在该示例中,假设您要单元测试预付款逻辑和后付款逻辑SaleAction......您不能因为SaleAction耦合CreditCardService并且可能正在运行您的测试将产生虚假付款.

现在与DI相同的例子:

 class SaleAction{

     private BillingService billingService;

     public SaleAction(BillingService service){
       billingService = service; //DI
     }

     public void pay(long amount){
       //pre payment logic
       billingService.pay(amount);
       //post payment logic
     }

    }
Run Code Online (Sandbox Code Playgroud)

现在SaleAction与任何实现分离,这意味着在你的测试中你可以做到SaleAction action = new SaleAction(new DummyBillingService());.

希望有所帮助,还有关于DI 文章,由Martin Fowler撰写,你可以在这里找到

  • 不依赖具体实现是OOP的核心,不仅仅是DI. (4认同)
  • @Pablo - "单元测试对于软件开发是强制性的" - 嗯,如果没有单元测试我就无法工作,但我认为即使大多数软件都有单元测试覆盖率. (2认同)