SpringBootWeb 篇-深入了解分层解耦与 IOC&DI(通过实现案例来讲解)
创始人
2024-12-01 16:36:03
0

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍

文章目录

        1.0 分层解耦概述

        2.0 分层解耦 - 三层架构

        2.1 控制器层(Controller)

        2.2 服务层(Service)

        2.3 持久层(Dao)

        3.0 分层解耦 - IOC&DI 概述

        3.1 内聚与耦合

        3.2 那么如何来实现低耦合呢?

        3.3 IOC 详解

        3.3.1 Bean 组件扫描

        3.4 DI 详解

        3.4.1 解决容器中存在多个相同类型的 bean 问题

        3.4.2 @Resource 与 @Autowired 区别

        4.0 通过案例深入了解三层架构与 IOC&DI


        1.0 分层解耦概述

        在 SpringBootWeb 开发中,分层解耦是一种常见的设计原则,用于将应用程序的不同功能模块分成不同的层次,每个层次负责不同的功能,从而实现代码的可维护性、可扩展性和可测试性。常见的分层结构包括控制器层、服务层、持久层等。

        2.0 分层解耦 - 三层架构

        可以实现不同层次之间的解耦,每个层次只需关注自己的职责,降低了各层次之间的耦合度,提高了代码的可维护性和可扩展性。

        2.1 控制器层(Controller)

        负责接收请求、处理请求参数、调用服务层处理业务逻辑,并返回响应结果给客户端。控制器层应该只包含与 HTTP 请求相关的逻辑,不应该包含业务逻辑。

        简单来说,控制层,接收前端发送的请求,对请求进行处理,并响应数据。

        2.2 服务层(Service)

        负责处理业务逻辑,包括数据处理、业务规则校验、调用持久层进行数据持久化等操作。服务层应该尽量保持独立,不涉及与外部系统的交互。

        简单来说,业务逻辑层,处理具体的业务逻辑。

        2.3 持久层(Dao)

        负责与数据库进行交互,包括数据的增删改查操作。持久层应该尽量保持独立,不涉及业务逻辑的处理。

        简单来说,数据访问层(持久层),负责数据访问操作,包括数据的增、删、改、查操作。

        3.0 分层解耦 - IOC&DI 概述

        在讲解 IOC&DI 之前,先来讲解一下内聚和耦合。

        3.1 内聚与耦合

        1)内聚:软件中各个功能模块内部的功能联系。

        内聚度高意味着模块内部元素之间的联系紧密,功能单一,实现特定的功能。内聚度低则表示模块内部元素之间联系松散,功能复杂,实现多种功能。

        简单来说,高内聚指每个方法或者每个类中,只有单一的功能。

        2)耦合:衡量软件中各个层/模块之间的依赖、关联的程度。

        因此,内聚度高、耦合度低是设计良好的软件模块的特征,可以提高模块的可维护性、可扩展性和可重用性。因此,在软件设计中,需要尽量提高模块的内聚度,降低模块之间的耦合度。

        简单来说,就是简单层与层之间的依赖性,比如说,服务层将相关代码进行修改之后,对于持久层的代码尽量是维持不变的效果,程序也能正确执行。

        3.2 那么如何来实现低耦合呢?

        通过 SpringBoot 框架提供的 IOC&DI 来实现。

        1)控制反转:Inversion of Control,简称 IOC 。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。

        2)依赖注入:Dependency Injection,简称 DI 。容器为应用程序提供运行时所依赖的资源,称为依赖注入。

        3)Bean 对象:IOC 容器中创建、管理的对象,称为 Bean 。

        3.3 IOC 详解

        把类用 @Component 注解,会先自动创建对象,再将创建好的对象放到容器中。该对象就可以被称为 Bean 对象。

        要把某个对象交给 IOC 管理,需要在对应的类上加上如下注解:

        1)Component:声明 bean 的基础注解。

        2)Controller:@Component 的衍生注解,标注在控制器类上。

        3)Service:@Component 的衍生注解,标注在业务类上。

        4)Repository:@Component 的衍生注解,标注在数据访问类上。

        3.3.1 Bean 组件扫描

        前面声明 bean 的四大注解,要想生效,还需要被组件扫描注解 @ComponentScan 扫描。

        @ComponentScan 注解虽然没有显示配置,但是实际上已经包含在启动类声明注解 @SpringBootApplication 中,默认扫描的范围是启动类所在包及其子包。

注意事项:

        声明 bean 的时候,可以通过 value 属性指定 bean 的名字,如果没有指定,默认为类名首字母小写。

        使用以上四个注解都可以声明 bean ,但是在 SpringBoot 集成 web 开发中,声明控制器 bean 只能用 @Controller 。

 

        3.4 DI 详解

        变量名用 @Autowired 注解,会根据变量的类型从容器中取出该类型的 Bean 对象,并将该对象赋值为变量名,这就是依赖注入。

        3.4.1 解决容器中存在多个相同类型的 bean 问题

        如果容器中只有一个类型,那么用 @Autowired 注解来将对象引入,是没有问题的;但是存在多个相同类型的 bean ,将会出错。

解决方法:

        1)@Primary:通过该注解,指定 bean 对象的优先级。

        2)@Autowired + @Qualifier("bean 的名称"):就可以通过对应的类型注入和指定 bean 对象名进行依赖注入了。

        3)@Resource(name="bean 的名称"):通过 bean 对象名进行依赖注入

        3.4.2 @Resource 与 @Autowired 区别

        1)@Autowired 是spring 框架提供的注解,而 @Resource 是 JDK 提供的注解。

        2)@Aurowired 默认是按照类型注入,而 @Resource 默认是按照名称注入。

        4.0 通过案例深入了解三层架构与 IOC&DI

未分层的代码框架:

import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;  import java.util.List;   //构建Results类 //添加demo4j依赖 //准备数据xml格式 @RestController public class project {      @RequestMapping("/requestList")     public Results requestList(){          //获取数据         String file = "src/main/java/org/example/Project/resource.xml";         List empList = ParseXml.parse(file);          //对数据进行处理         empList.stream().forEach(emp -> {             if (emp.getGender().equals("1")){                 emp.setGender("男");             }else if (emp.getGender().equals("2")){                 emp.setGender("女");             }              if (emp.getJod().equals("1")){                 emp.setJod("学生");             } else if (emp.getJod().equals("2")) {                 emp.setJod("老师");             }         });          //响应数据         return new Results(1,"成功",empList);      }  }

        对于以上的代码,很明显可以分层为:Controller、Service、DAO 。出现冗余、内聚程度不高,对后期代码维护难。

持久层(DAO)代码:

接口:

import org.example.Project.Emp;  import java.util.List;  public interface Dao {      List getList(); }

实现类:

import org.example.Project.Emp; import org.example.Project.ParseXml; import org.springframework.stereotype.Repository;  import java.util.List;  @Repository public class DAO_A implements Dao{      @Override     public List getList() {         //获取数据         String file = "src/main/java/org/example/Project/resource.xml";         List list = ParseXml.parse(file);         return list;     } }

服务层(Service)代码:

接口:

​ import org.example.Project.Emp;  import java.util.List;   public interface Service {      List service();  }

实现类:

import org.example.Project.DAO.Dao; import org.example.Project.Emp; import org.springframework.beans.factory.annotation.Autowired;  import java.util.List;  @org.springframework.stereotype.Service public class ServiceA implements Service{      //需要获取的数据     @Autowired     Dao dao_a;      @Override     public List service() {         List empList = dao_a.getList();         //对数据进行处理         empList.stream().forEach(emp -> {             if (emp.getGender().equals("1")){                 emp.setGender("男");             }else if (emp.getGender().equals("2")){                 emp.setGender("女");             }              if (emp.getJod().equals("1")){                 emp.setJod("学生");             } else if (emp.getJod().equals("2")) {                 emp.setJod("老师");             }         });         return empList;     } }

控制层(Controller)代码:

@RestController public class project {      @Autowired     Service s;      @RequestMapping("/requestList")     public Results requestList(){          //响应数据         return new Results(1,"成功",s.service());     } }

XML 文件 :

                小扳手         20                   1                   1                   小童         21                   2                   2                   小蜜蜂         3                   2                   1                   姬小满         20                   2                   2       

运行结果:

 

相关内容

热门资讯

透视模拟器!wepoker是不... 透视模拟器!wepoker是不是有人用挂,we-poker辅助软件教程(本来是有挂);1、进入到we...
透视真的!hhpoker辅助挂... 透视真的!hhpoker辅助挂下载,德州局怎么透视,详细教程(有挂攻略)1)hhpoker辅助挂下载...
透视挂!拱趴大菠萝有什么挂,佛... 透视挂!拱趴大菠萝有什么挂,佛手在线有挂吗,黑科技教程(有挂工具)1、拱趴大菠萝有什么挂系统规律教程...
透视脚本!aapoker透视怎... 透视脚本!aapoker透视怎么用,aapoker发牌逻辑,透牌教程(有挂方法)1、进入游戏-大厅左...
透视有挂!wepoker有什么... 透视有挂!wepoker有什么规律,wepoker俱乐部辅助(总是是有挂)在进入wepoker俱乐部...
透视真的!hhpkoer辅助器... 透视真的!hhpkoer辅助器视频,hhpoker透视脚本下载,黑科技教程(有挂细节);一、hhpo...
透视实锤!拱趴大菠萝万能挂图解... 透视实锤!拱趴大菠萝万能挂图解,哈糖大菠萝攻略,必备教程(有挂解密)所有人都在同一条线上,像星星一样...
透视总结!wepoker可以透... 透视总结!wepoker可以透视码,wepoker怎么开辅助(切实有挂)1、透视总结!wepoker...
透视软件!aapoker免费透... 透视软件!aapoker免费透视脚本,aapoker俱乐部靠谱吗,玩家教程(有挂教程)aapoker...
透视规律!hhpoker德州作... 透视规律!hhpoker德州作弊,hhpoker破解工具,2025新版技巧(有挂插件)1、实时hhp...