0%

spring-ioc 设计思想

在一个大型项目当中,由于代码的复杂度高,就产生了耦合度过高的问题,即类与类之间的依赖程度过高,如果此时一个类出现了bug或者业务上的需求,需要修改代码,那么其他的类也受到影响,导致大量的修改,造成可维护性差的问题。为了降低软件设计中的耦合度,更好的处理类之间的依赖关系,因此出现了 IOC (控制反转) 这种设计模式。

IOC 思想

把通过new产生对象的这种方式,改变通过把类的定义以及属性和方法编写到.xml配置文件中,在运行的时候,Java会利用”反射”的方式,在外部根据写好的.xml配置文件中的类定义,生成相应的对象—这就把源码和生成对象隔离了。

所谓反射的方式,也就是根据配置文件中的全类名,来获得该类的对象。

以上仅仅是在外部产生了对象,为了业务的需求,程序不可能没有依赖关系。我们也会在.xml配置文件中编写类与类之间的关系,比如说Service类引用了Dao类的对象。但值得注意的是,容器(比如Spring)会自动把生成的对象根据编写好的依赖关系,注入到软件中去,即把实例化的Dao类对象注入到Service类下的引用中,从而产生依赖关系。通过这种方式产生依赖关系,大大降低了源代码的耦合度。因为需要改动的时候,只要改动.xml配置文件即可。

这就是”依赖注入”,把外部生成的实例化对象注入到源码中该对象的引用中去,使程序之间产生依赖关系。这是IOC的一个重要的实现方式。

以上所说的是IOC完成了底层部分的工作。IOC实际上所有的工作包括: 创建对象,管理对象(通过依赖注入),整合对象,配置对象以及管理对象的生命周期。

理解 IOC 主要是通过一下 2 点:

  1. 谁控制谁?IoC 容器控制了对象;控制什么?控制了外部资源获取。
  2. 传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,是正转;而反转则是由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象。依赖对象的获取被反转了。

理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”:

  • 谁依赖于谁:应用程序依赖于IoC容器;
  • 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
  • 谁注入谁: IoC 容器注入应用程序某个对象,应用程序依赖的对象;
  • 注入了什么:注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

IoC 和 DI 是同一个概念的不同角度描述,相对 IoC 而言,依赖注入明确描述了被注入对象依赖 IoC 容器配置依赖对象。

示例

传统程序设计都是通过new主动去创建相关对象然后再组合起来:

image-20210824180638418

用户类

1
2
3
4
5
public class User {
public String getUserName() {
return "chenpeng";
}
}

用户业务类

1
2
3
4
5
6
7
8
9
10
11
public class UserService {
private User user;

public UserService(User user) {
this.user = user;
}

public void getUserName() {
System.out.println(user.getUserName());
}
}

客户端

1
2
3
4
5
6
7
public class Client {
public static void main(String[] args) {
User user = new User();
UserService userService = new UserService(user);
userService.getUserName();
}
}

当有了容器后,在客户端类中不再主动去创建这些对象了(由IOC类完成)

image-20210824180739462

IOC 类

1
2
3
4
5
6
7
8
public class IOC {
private User user = new User();
private UserService userService = new UserService(user);

public UserService getUser() {
return userService;
}
}

客户端

1
2
3
4
5
6
7
8
public class Client {
public static void main(String[] args) {
IOC ioc = new IOC(); // IOC容器负责创建用户类以及属性的注入
// 直接从容器中获取用户类
UserService userService = ioc.getUser();
userService.getUserName();
}
}