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;
}
...
}
您现在可以注入任何您喜欢的实现,而无需触及代码。
我无法理解这两种模式之间的区别。我觉得这两个是相同但不同的程序模式。刚刚进入 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;
}
...
}
您现在可以注入任何您喜欢的实现,而无需触及代码。