Service层和Dao层是否需要每个类都加上接口? -- 知识铺
来源:https://urlify.cn/Vjua2e
👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利
新项目:仿小红书(微服务架构)正在更新中… , 全栈前后端分离博客项目 2.0 版本完结啦, 演示链接:http://116.62.199.48/">http://116.62.199.48/ 。全程手摸手,后端 + 前端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,直到项目上线。目前已更新了255小节,累计40w+字,讲解图:1716张,还在持续爆肝中.. 后续还会上新更多项目,目标是将Java领域典型的项目都整一波,如秒杀系统, 在线商城, IM即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,已有1300+小伙伴加入(早鸟价超低)
前几天看技术交流群的话题,又刷到了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 —实现在另一个包里
-
Service2
-
impl2 —新实现在另一个包里
-
Dao
相对而言,实际第一种方式相对更简单一点,只需要关注包层面。而第二种方式需要关注模块和包两个层面。另外,实际这两种方式都导致了项目中包含了不需要的逻辑代码。因为老逻辑都会被打进包里。
不过,从结构上来看,实际方式二的结构要比方式一的结构更清晰,因为从模块上能区分逻辑。
那有没有办法来结合两者的优点呢?答案是肯定的,而且操作起来也不复杂!
首先将接口和实现独立开,作为一个独立的模块:
-
Controller
-
Service — 接口模块
-
ServiceImpl
-
impl —实现在另一个包里
-
ServiceImpl2
-
impl2 —新实现在另一个包里
-
Dao
其次,调整打包配置,ServiceImpl 和 ServiceImpl2 二选一。既然 ServiceImpl 和 ServiceImpl2 是二选一,那 ServiceImpl 和ServiceImpl2 的包结构就可以相同。包结构相同了,那调整了依赖以后,依赖注入相关的配置就不需要调整了。调整后,项目结构看起来像这样:
-
Controller
-
Service — 接口模块
-
ServiceImpl
-
impl —实现在另一个包
-
ServiceImpl2
-
impl —新实现和老实现在相同的包中
-
Dao
现在,ServiceImpl 和 ServiceImpl2 模块中的包结构、类名都是一样的。那我们还需要接口模块吗?
假设,我们把Service接口模块去掉,结构变成了如下所示:
-
Controller
-
Service1 — 老实现
-
Service2 — 新实现
-
Dao
单纯的通过调整模块依赖,是否能实现 Service 的多实现?答案显而易见吧?
上面给出了不使用接口的理由。不过不使用接口并不是完全没有缺点的,主要问题就是在进行多实现的时候,没有一个强接口规范。即不能通过实现接口,借助 IDE 快速生成框架代码。对于没有实现的接口,IDE 也能给出错误提醒。
一个不太优雅的解决是,将原来的模块里的代码拷贝一份到新模块中,基于老代码来实现新的逻辑。
所以,如果一个项目需要多实现、且多实现数量较多(不过一般项目不会有多个实现的),则推荐使用接口。否则不需要使用接口。
本文针对「Service 层是否需要接口」这个问题,指出需要接口的理由的问题。以及个人对这个问题的观点,希望在评论区写出自己的理解 !
👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利
新项目:仿小红书(微服务架构)正在更新中… , 全栈前后端分离博客项目 2.0 版本完结啦, 演示链接:http://116.62.199.48/">http://116.62.199.48/ 。全程手摸手,后端 + 前端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,直到项目上线。目前已更新了255小节,累计40w+字,讲解图:1716张,还在持续爆肝中.. 后续还会上新更多项目,目标是将Java领域典型的项目都整一波,如秒杀系统, 在线商城, IM即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,已有1300+小伙伴加入(早鸟价超低)
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com"><img data-fileid="100015743" data-imgfileid="100051314" data-ratio="0.08658008658008658" data-src="https://mmbiz.qpic.cn/mmbiz_gif/TNUwKhV0JpTGQqtlGfEHkjibtshlaDwVKzjqq2pnpmYC14bKxDtSuhpWZWfVcicj5PFsoSMzuzicKIWZbsBpGXiaicg/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&tp=webp" data-type="gif" data-w="462" data-width="100%" data-original-style="outline: 0px;background-size: 16px;border-radius: 8px;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;word-spacing: 2px;display: block;visibility: visible !important;width: 577.977px !important;" data-index="6" src="https://mmbiz.qpic.cn/mmbiz_gif/TNUwKhV0JpTGQqtlGfEHkjibtshlaDwVKzjqq2pnpmYC14bKxDtSuhpWZWfVcicj5PFsoSMzuzicKIWZbsBpGXiaicg/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&tp=webp" _width="577.977px" data-order="0" alt="图片"></section><pre><pre><pre data-style="letter-spacing: 0.544px; font-size: 16px; color: rgb(63, 63, 63); word-spacing: 1px; line-height: inherit;"><section powered-by="xiumi.us" data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(230, 230, 230)" data-darkmode-original-color="rgb(0, 0, 0)" data-style="margin-right: 0.5em; margin-left: 0.5em; white-space: normal; font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif; color: rgb(0, 0, 0); letter-spacing: 0px; word-spacing: 2px;" data-mpa-template-id="1250" data-mpa-color="#ffffff" data-mpa-category="divider"><p data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(106, 104, 111)" data-darkmode-original-color="rgb(106, 104, 111)">1. <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&mid=2247522465&idx=1&sn=49da64cae0a62b0c2beac8e0ad2b420e&chksm=fd574827ca20c1314c036377d7698e1fe12a7e716a15a0cfb56d5870f209c3dded22dd848d26&scene=21#wechat_redirect" textvalue="我的私密学习小圈子~" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1">我的私密学习小圈子~</a></p><p data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(138, 138, 138)" data-darkmode-original-color="rgb(89, 89, 89)"><span>2. <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&mid=2247534922&idx=1&sn=6bfb7ca2b8997f1887ec2a7d1890622e&chksm=fd5799ccca2010da51a080f85274b0a349716a002dcadf0da247df280a537732d8b95c0d6c0a&scene=21#wechat_redirect" textvalue="分布式链路追踪:TraceIdFilter + MDC + Skywalking" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">分布式链路追踪:TraceIdFilter + MDC + Skywalking</a><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&mid=2247530313&idx=1&sn=5adf4981de7f0abbcb1bde27ee74ae56&chksm=fd57a7cfca202ed9351c8954bce05f159584f0219de7bd3ff12362e3c98b1cc752802bbe3db2&scene=21#wechat_redirect" textvalue="堪称最优秀的Docker可视化管理工具——Portainer你真的会用吗?" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1"></a></span></p><p data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(138, 138, 138)" data-darkmode-original-color="rgb(89, 89, 89)"><span>3. <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&mid=2247534922&idx=2&sn=4ffb5b1be2a19ee74c8358e2f9e105e3&chksm=fd5799ccca2010daa8fac1c60811af84ae8e2b6eca60ea2a49d68c154078e104f26df7e54924&scene=21#wechat_redirect" textvalue="微服务架构中10个常用的设计模式" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">微服务架构中10个常用的设计模式</a><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&mid=2247531213&idx=2&sn=f4d4ae2ffc511109f0917b8e15217e65&chksm=fd57aa4bca20235d13f288853171b10e40ebd9ce272880c36de9a40a2d136d32a665ac4ca2a6&scene=21#wechat_redirect" textvalue="常见踩坑点:双层 for 循环千万别这样写了!" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1"></a></span></p><p data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(106, 104, 111)" data-darkmode-original-color="rgb(106, 104, 111)">4. <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&mid=2247534774&idx=2&sn=09125d0e2d8f106e1cad7cfdbe3207a2&chksm=fd579830ca20112641818283bdf9e4d3fc08078494d853e4b88531cf59dad83f1144f66003d6&scene=21#wechat_redirect" textvalue="Hutool 中的这些工具类,太实用了!" linktype="text" imgurl="" imgdata="null" data-itemshowtype="11" tab="innerlink" data-linktype="2">Hutool 中的这些工具类,太实用了!</a><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&mid=2247531127&idx=1&sn=82474072ee5c6ca729f17ec75ded9e72&chksm=fd57aaf1ca2023e7c9960deabf609a3b75a2da35fa0717aea6ef958025948da270dc08930007&scene=21#wechat_redirect" textvalue="SpringBoot:一个注解就能帮你下载任意对象" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1"></a></p></section><p data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(168, 168, 168)" data-darkmode-original-color="rgb(62, 62, 62)" data-style="margin-right: 0.5em; margin-left: 0.5em; white-space: normal; font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif; letter-spacing: 0px; word-spacing: 2px; color: rgb(62, 62, 62); text-align: center;"><img data-fileid="100015744" data-imgfileid="100051315" data-ratio="0.5555555555555556" data-s="300,640" data-type="gif" data-w="639" data-src="https://mmbiz.qpic.cn/sz_mmbiz_gif/knmrNHnmCLEVGGmicJODkfibhcqyUwmTSC8CUvAMG78wPemfibvQ502uFs9jlziaLP50YcTs4rL9hQuzX32PAUOPHA/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&wx_co=1&tp=webp" data-original-style="outline: 0px;border-radius: 8px;background-position: center center;background-repeat: no-repeat;background-color: rgb(238, 237, 235);background-size: 22px;border-width: 1px;border-style: solid;border-color: rgb(238, 237, 235);visibility: visible !important;width: 601px !important;" data-index="7" src="https://mmbiz.qpic.cn/sz_mmbiz_gif/knmrNHnmCLEVGGmicJODkfibhcqyUwmTSC8CUvAMG78wPemfibvQ502uFs9jlziaLP50YcTs4rL9hQuzX32PAUOPHA/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&wx_co=1&tp=webp" _width="601px" crossorigin="anonymous" alt="图片"></p><pre data-style="letter-spacing: 0.544px; text-size-adjust: auto; word-spacing: 2px; color: rgb(89, 89, 89);"></pre></pre></pre></pre>
<pre data-style="letter-spacing: 0.544px; text-size-adjust: auto; word-spacing: 2px; color: rgb(89, 89, 89);"><p data-style="margin-top: 5px; margin-bottom: 5px; white-space: normal; color: rgb(62, 62, 62); letter-spacing: 0.544px; font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif; font-size: 14px; line-height: normal;"><span>最近面试BAT,整理一份面试资料</span><span>《<strong>Java面试BATJ通关手册</strong>》</span><span>,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。</span></p><p data-style="margin-top: 15px; margin-bottom: 15px; letter-spacing: 0.544px; white-space: pre-line; line-height: 30px; color: rgb(74, 74, 74); font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;"><span>获取方式:点“</span><span>在看</span><span>”,关注公众号并回复 </span><span>Java</span><span> 领取,更多内容陆续奉上。</span></p></pre><pre><p data-tool="mdnice编辑器"><span>PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下</span><strong>“<span>在看</span>”</strong><span>,加个</span><strong>“<span>星标</span>”</strong><span>,这样每次新文章推送才会第一时间出现在你的订阅列表里。</span></p><p data-tool="mdnice编辑器"><span>点<strong>“在看”</strong>支持小哈呀,谢谢啦</span></p></pre>
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/geek001/post/20240505/Service%E5%B1%82%E5%92%8CDao%E5%B1%82%E6%98%AF%E5%90%A6%E9%9C%80%E8%A6%81%E6%AF%8F%E4%B8%AA%E7%B1%BB%E9%83%BD%E5%8A%A0%E4%B8%8A%E6%8E%A5%E5%8F%A3--%E7%9F%A5%E8%AF%86%E9%93%BA/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com