【SpringBootWeb入门-9】分层解耦-分层解耦(IOC-DI引入)

发布时间 2023-12-11 22:53:02作者: hiker0412

1、分层解耦概念

上一节我们讲解了三层架构,我们把web程序分为了三层,分别是Conroller控制层、Service业务逻辑层、DAO数据访问层,这一节我们来讲解分层之后的解耦。

解耦的含义就是接触耦合,首先我们来介绍两个概念:内聚、耦合

  • 内聚:软件中各个功能模块内部的功能联系。
  • 耦合:衡量软件中各个层/模块之间的依赖、关联的程度。

我们上一节所写的EmpController层,里面的实现功能是处理员工业务,与员工无关的我们不会写在里面,这里就是功能的高内聚;然后EmpController层依赖Service层,Service层依赖DAO层,这里就是所谓的耦合。

我们的软件设计有一个原则:高内聚低耦合。

高内聚:模块里面的功能联系越紧密越好,就比如员工管理的EmpController层,仅仅实现员工的逻辑处理;

低耦合:尽可能降低层与层之间、模块与模块之间的依赖,最好能做到解除耦合,层与层之间没有耦合,即使Service层的代码发生改变,也不会影响Controller层与DAO层的代码,这样代码的可扩展性会更好。

2、三层架构耦合分析

我们上一节所编写的三层架构中,Controller调用Service,需要new一个Service的实现,如下图:

如果Service需要切换,从EmpServiceA切换到EmpServiceB,那么我们的Controller层也要重新改动,把new的对象从EmpServiceA改成EmpServiceB。我们发现,Service层的代码改动,我们的Controller层代码也需要改动,我们就叫Controller层代码与Service层代码产生了耦合,接下来我们来分析如何解除耦合。

3、三层架构解除耦合

要想解耦,我们在Controller层的 就不能直接 new Service层的实现类了,一旦 new 了 Service层实现类,两层之间则会耦合起来,所以第一步要把 new Service层的实现类部分代码删除。

但是删掉new Service层的实现类部分代码,直接运行代码会报错,原因是因为声明了一个类变量,但是却没有给其赋值,其值则会为null,在运行的时候则会报错空值。

那我们怎么去解决这个问题呢?我们的思路如下:springboot提供一个容器,容器用来存放对象,假如我们用来存放EmpServiceA的实现,只需要把EmpServiceA对象放在容器中,接下来Controller在运行过程中需要依赖EmpService,我们可以在容器中查找EmpServiceA这个对象,查找到后将容器中的对象赋值给Controller的变量empService;如果要切换EmpServiceB,基于EmpServiceB创建一个对象放到容器中,此时Controller在运行中,它也会在容器中查找到EmpServiceB对象,来赋值给Controller的变量empService。这样我们就会发现,即使Service层的实现类发生了变化,Controller的代码也不用再改动,这样就完成了解耦的操作。

在这里还存在两个问题:

1、EmpService对象怎么交给容器来管理;

2、容器怎么来提供给Controller程序它所依赖的资源。

这里就涉及到了springboot的非常重要的两个概念:控制反转依赖注入

控制反转: Inversion Of Control,简称IOC,springboot的第一大核心。以前都是需要什么对象直接程序自己new,现在需要的对象创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。
依赖注入: Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。
Bean对象:IOC容器中创建、管理的对象,称之为bean。

关于分层解耦的思想上述已经讲解完毕,下一篇我们通过IOC以及DI来完成分层解耦的具体实现。