阅读本文大概需要 5 分钟。

前几天刷头条又刷到了「Service层和Dao层真的有必要每个类都加上接口吗?」这个问题,之前简单回答了一波,给出的观点是「看情况」现在结合我参与的项目以及阅读的一些项目源码来看。

如果项目中使用了像Spring这样的依赖注入框架,那可以不用接口!

先来说说为什么使用了依赖注入框架以后,可以不使用接口!我整理了支持Service层和Dao层需要加上接口的理由,总结下来就这么三个:可以在尚未实现具体Service逻辑的情况下编写上层代码,如Controller对Service的调用

Spring默认是基于动态代理实现AOP的,动态代理需要接口

可以对Service进行多实现

实际上,这三个理由都站不住脚!先说说第一个理由:「上层可以在下层逻辑没有实现的情况下进行编码」!很典型的面向接口编程,对层与层之间进行了解耦,看起来好像没有问题。这种开发方式适合不同模块之间是由不同的人或项目组开发的,因为沟通的成本比较大。同时避免由于项目组之间开发进度的差异而相互影响。

不过让我们回想一下,在一般项目开发里面,有多少项目组是按层来切分开发任务的呢?实际上,大部分的项目都是按照功能划分的。即使是现在前后端分离的情况,单纯的后端开发也是按照功能模块进行任务划分,即一个人负责从Controller层到DAO层的完整逻辑处理。

在这种情况下,每一层都先定义一个接口,再去实现逻辑,除了增加了开发人员的工作量(当然,如果代码量计入工作量的话,那开发人员应该也不是太排斥接口的!),实际没有任何用处。

如果开发人员想在下层逻辑没有完成的情况下,先开发上层逻辑,可以先编写下层类的空方法来先完成上层的逻辑。这里推荐一个个人比较喜欢的开发流程,自上向下的编码流程:先在Controller层编写逻辑,遇到需要委托Service调用的地方,直接先写出调用代码。

优先完成Controller层的流程

然后使用IDE的自动补全,对刚才调用下层的代码生成对应的类和方法,在里面添加TODO

等所有的类和方法都补全了,再基于TODO,按照上面的流程去一个个的完善逻辑。

此方法可以使你对业务流程有比较好的理解。

对于第二个理由,就完全不成立了。Spring默认是基于动态代理的,不过通过配置是可以使用CGLib来实现AOP。CGLib是不需要接口的。最后一个理由是「可以对Service进行多实现」。这个理由不充分,或者说没有考虑场景。实际上在大多数情况下是不需要多实现,或者说可以使用其它方式替代基于接口的多实现。另外,对于很多使用了接口的项目,项目结构也是有待商榷的!下面,我们结合项目结构来说明。一般项目结构都是按层来划分的,如下所示:Controller

Service

Dao

对于不需要多实现的情况,也就不需要接口了。上面的项目结构即可满足要求。对于需要多实现的情况,无论是现在需要,还是后面需要。这种情况下,看起来好像是需要接口。此时的项目结构看起来像这样:Controller

Service--- 接口在一个包中

impl --- 实现在另一个包里

Dao

对于上面的结构,我们来考虑多实现的情况下,该怎么处理?第一种方式,是在Service中新增一个包,在里面编写新的逻辑,然后修改配置文件,将新实现作为注入对象。Controller

Service---- 接口在一个包中

impl ---实现在另一个包里

impl2 ---新实现在另一个包里

Dao

第二种方式,是新增一个Service模块,在里面编写新的逻辑(注意这里的包和原来Service的包不能相同,或者包相同,但是类名不同,否则无法创建类。因为在加载时需要同时加载两个Service模块,如果包名和类名都相同,两个模块的类全限定名就是一样的了!),然后修改配置文件,将新逻辑作为注入对象。Controller

Service---- 接口在一个包中

impl ---实现在另一个包里

Service2impl2 ---新实现在另一个包里

Dao

相对而言,实际第一种方式相对更简单一点,只需要关注包层面。而第二种方式需要关注模块和包两个层面。另外,实际这两种方式都导致了项目中包含了不需要的逻辑代码。因为老逻辑都会被打进包里。不过,从结构上来看,实际方式二的结构要比方式一的结构更清晰,因为从模块上能区分逻辑。那有没有办法来结合两者的优点呢?答案是肯定的,而且操作起来也不复杂!首先将接口和实现独立开,作为一个独立的模块:Controller

Service --- 接口模块ServiceImpl

impl ---实现在另一个包里

ServiceImpl2impl2 ---新实现在另一个包里

Dao

其次,调整打包配置,ServiceImpl和ServiceImpl2二选一。既然ServiceImpl和ServiceImpl2是二选一,那ServiceImpl和ServiceImpl2的包结构就可以相同。包结构相同了,那调整了依赖以后,依赖注入相关的配置就不需要调整了。调整后,项目结构看起来像这样:Controller

Service --- 接口模块ServiceImpl

impl ---实现在另一个包

ServiceImpl2impl ---新实现和老实现在相同的包中

Dao

现在,ServiceImpl和ServiceImpl2模块中的包结构、类名都是一样的。那我们还需要接口模块吗?假设,我们把Service接口模块去掉,结构变成了如下所示:Controller

Service1 --- 老实现

Service2 --- 新实现

Dao

单纯的通过调整模块依赖,是否能实现Service的多实现?答案显而易见吧?

上面给出了不使用接口的理由。不过不使用接口并不是完全没有缺点的,主要问题就是在进行多实现的时候,没有一个强接口规范。即不能通过实现接口,借助IDE快速生成框架代码。

对于没有实现的接口,IDE也能给出错误提醒。一个不太优雅的解决是,将原来的模块里的代码拷贝一份到新模块中,基于老代码来实现新的逻辑。

所以,如果一个项目需要多实现、且多实现数量较多(不过一般项目不会有多个实现的),则推荐使用接口。否则不需要使用接口。本

文针对「Service层是否需要接口」这个问题,指出需要接口的理由的问题。以及个人对这个问题的观点,希望在评论区写出自己的理解 !

为什么要用impl继承service层_讨论:Service层需要接口吗?相关推荐

  1. java遮罩层_页面遮罩层 - javaalex的个人空间 - OSCHINA - 中文开源技术交流社区

    一. 基于ajax请求的遮罩层: $.ajax({ type:'POST', url:url, data:obj, dataType:'json', beforeSend: function () { ...

  2. 数据仓库—stg层_数据仓库之Hive快速入门 - 离线实时数仓架构

    数据仓库VS数据库 数据仓库的定义: 数据仓库是将多个数据源的数据经过ETL(Extract(抽取).Transform(转换).Load(加载))理之后,按照一定的主题集成起来提供决策支持和联机分析 ...

  3. 数据仓库—stg层_有赞数据仓库实践之路

    原标题:有赞数据仓库实践之路 一.大数据环境下的有赞数仓 关于数据仓库,在维基百科中将它定义为 用于报表和数据分析的系统,是商务智能 Business Intelligence 的核心部分.在数据仓库 ...

  4. 将Dao层注入到Service层

    三层架构:界面层,业务逻辑层,数据访问层 三层之间的交互: 用户使用界面层(Controller)-业务逻辑层(Service)-数据访问层(Dao层)----数据库(mysql) 三层对应的处理框架 ...

  5. java的dao层_Java中DAO层、Service层和Controller层的区别

    DAO层: DAO层叫数据访问层,全称为data access object,属于一种比较底层,比较基础的操作,具体到对于某个表的增删改查,也就是说某个DAO一定是和数据库的某一张表一一对应的,其中封 ...

  6. java代码生成器,生成controller、service、mapper、entity 层,只需要六步

    通过数据库表名创建 controller.service.mapper.entity 层. CodeGenerator 类 package test;import com.baomidou.mybat ...

  7. java dao层 service层_Java中DAO层、Service层和Controller层的区别

    DAO层: DAO层叫数据访问层,全称为data access object,属于一种比较底层,比较基础的操作,具体到对于某个表的增删改查,也就是说某个DAO一定是和数据库的某一张表一一对应的,其中封 ...

  8. SpringBoot - 实践阿里巴巴【Manager 层_通用业务处理层】

    文章目录 规范 对比传统MVC 小栗子 V1.0 传统写法 V2.0 引入Manager层 源码 规范 对比传统MVC 说几个弊端 Service层代码臃肿 Service层易出现大事务,事务嵌套,易 ...

  9. 框架:DAO,Service,Controller,View层之间的逻辑关系

    Dao层: Dao层是数据访问层,负责与数据库进行联络的一些任务封装在此,Dao层的设计首先是设计Dao接口,然后在Spring的配置文件中定义此接口的实现类,最后就可以通过模块调用此接口来进行数据业 ...

最新文章

  1. 报告:采用人工智能并不意味着成功
  2. JAVA图形界面(GUI)之布局管理器
  3. VS Code 的常用快捷键和插件
  4. Apache2.4开启php
  5. matlab音频基频的提取,(620512681) 自相关基频提取算法的MATLAB实现
  6. 初中生学计算机视频,推荐一下适合中学生的在线视频学习网站
  7. 【README】二叉树刷题框架
  8. 美团面试官:讲清楚MySQL结构体系,立马发offer
  9. Android 驱动(16)---AOSP如何单独build kernel
  10. php 长剑设计模式,PHP设计模式(创建型)
  11. MCU_segger-JLINK批处理脚本烧录工具-JFlash
  12. C# WPF如何设置oxyplot的折线图禁止鼠标滚轮缩放
  13. 免费获得minecraft账号,快来试试!!!
  14. 实践练习一(必选):OceanBase Docker 体验(小麦苗版)
  15. 无尽神域服务器维护,关于对无尽神域的感受亲爱的无尽神域开发团队:
  16. 最近项目开发再一次遇到了启动idea报错:Plugin Error Problems found loading plugins: Plugin “GlassFish Integration“ was
  17. 农业信息化技术导论划重点笔记-农业工程与信息技术
  18. 为何机房要升级动环监控系统?
  19. root认证失败 tera term_解决Ubuntu 18.04使用root账户登录显示“认证失败”
  20. 正则表达式——Pattern.DOTALL

热门文章

  1. linux下修改Mysql、Oracle以及mongoDB数据库密码
  2. 吃鸡模拟器战斗服务器无响应,全面吃鸡模拟器进不去怎么办?进不去很卡解决方法[多图]...
  3. 支付宝推出AR实景红包,让你和捉小精灵一样抢红包
  4. 现有的分词算法,主要分为哪三大类?
  5. 关于Unity3d中的自动寻路
  6. hexo站点目录存放html,hexo目录结构小探
  7. java 检测网络连接,使用java检测网络连接情况
  8. 多媒体【通知,拍摄及相册】
  9. 获取手机Gps地理位置并获取Gps信号强弱
  10. 腾讯社招前端面经(成都)