Spring Java 对象依赖注入

Spring Java Object Dependency Injection

我无法理解这两种模式之间的区别。我觉得这两个是相同但不同的程序模式。刚刚进入 spring.

模式 1 - 通过构造函数和 setter 方法进行依赖注入

class Employee{

   Address address ;

   public Employee(Address address ) {
    this.address = address;
   }
   public void setAddress(Address address ) {
    this.address = address;
   }

}

模式 2 - 旧 java 对象创建

class Employee{
    Address address ;
    public Employee(){
      address = new Address();
    }
}

我不明白为什么模式 1 很好(loosly coupled) 而模式 2 是 tightly coupled。无论如何 Employee 应该取决于 Address class 。

在第一种情况下,您可以在运行时动态发送地址 class(这本质上是依赖注入的意思),而在第二种情况下,在编码时您可能不知道地址对象需要什么.

假设您有一个数据库连接对象而不是地址对象。让我们假设您的员工对象出于任何原因需要此数据库对象。

现在,如果您不知道要连接到哪个数据库(您可能必须连接到不同的数据库,基于 env.prod、dev、qa 等),第二种方法不起作用。在第一种方法中,您可以从配置文件中获取此配置,然后在运行时动态发送连接对象。

因为如果您使用的是模式 1,那么假设您想添加其他功能会更容易。该字段(在您的情况下是地址)可以很容易地替换为另一个具体 class.

例如,假设您要创建一个日志记录框架。

模式 1

public class LoggingManager {
    private Logger logger;

    public void doLog(String message) {
        logger.log(message);
    }

    //setter getter here 
}

通过使用模式 1,您可以让 ioc 容器分配日志管理器将执行的日志记录类型(它可以记录到文件或控制台,或者可能将日志信息存储到数据库中,因此,它是松散耦合的).

模式 2

public class LoggingManager {
    private Logger logger;

    public LoggingManager() {
        logger = new FileLogger();
    }

    // same method as above
}

如您在代码片段中所见,日志管理器只能做一件事,将日志信息记录到文件中。

你的例子有点简单,也许简单到可以抓住 dependency injection 的全部优点,但第一个模式更好,因为你将 Employe class 与Address

在这种情况下:

class Employee {
    private Address address ;
    public Employee() {
        address = new Address();
    }
}

您的 Employee class 负责构建一个 Address。它使用 new Address()。你现在固定在这种地址。如果要更改地址实现,则需要更改代码。

But an address comes in many shapes and sizes。当您在代码中仅实例化一种类型的地址时,您如何使 Employee 同时使用欧洲地址和日本地址?

为了更清楚地说明这一点,让我们稍微扩展一下您的示例,并将 Address 视为一个接口。 Programming to an interface is another good practice。所以现在我们有了一个接口和一个实现:

class Employee {
    private Address address;
    public Employee() {
      address = new JapaneseAddress();
    }
    ...
}

现在看到问题了吗?如果您以后想要一个欧洲地址,您将需要进入代码并进行一些更改。

如果你有这个:

class Employee {
   private Address address ;

   public Employee(Address address) {
      this.address = address;
   }
   ...
}

您现在可以注入任何您喜欢的实现,而无需触及代码。