《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
如果开发人员想在下层逻辑没有完成的情况下,先开发上层逻辑,可以先编写下层类的空方法来先完成上层的逻辑。
这里推荐一个个人比较喜欢的开发流程,自上向下的编码流程:
先在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也能给出错误提醒。
最后
ActiveMQ消息中间件面试专题
- 什么是ActiveMQ?
- ActiveMQ服务器宕机怎么办?
- 丢消息怎么办?
- 持久化消息非常慢怎么办?
- 消息的不均匀消费怎么办?
- 死信队列怎么办?
- ActiveMQ中的消息重发时间间隔和重发次数吗?
ActiveMQ消息中间件面试专题解析拓展:
redis面试专题及答案
- 支持一致性哈希的客户端有哪些?
- Redis与其他key-value存储有什么不同?
- Redis的内存占用情况怎么样?
- 都有哪些办法可以降低Redis的内存使用情况呢?
- 查看Redis使用情况及状态信息用什么命令?
- Redis的内存用完了会发生什么?
- Redis是单线程的,如何提高多核CPU的利用率?
Spring面试专题及答案
- 谈谈你对 Spring 的理解
- Spring 有哪些优点?
- Spring 中的设计模式
- 怎样开启注解装配以及常用注解
- 简单介绍下 Spring bean 的生命周期
Spring面试答案解析拓展
高并发多线程面试专题
- 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
- Java 中新的 Lock 接口相对于同步代码块(synchronized block)有什么优势?如果让你实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。
- Java 中 wait 和 sleep 方法有什么区别?
- 如何在 Java 中实现一个阻塞队列?
- 如何在 Java 中编写代码解决生产者消费者问题?
- 写一段死锁代码。你在 Java 中如何解决死锁?
高并发多线程面试解析与拓展
jvm面试专题与解析
- JVM 由哪些部分组成?
- JVM 内存划分?
- Java 的内存模型?
- 引用的分类?
- GC什么时候开始?
JVM面试专题解析与拓展!
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
死锁代码。你在 Java 中如何解决死锁?
高并发多线程面试解析与拓展
[外链图片转存中…(img-ApGi3FAe-1714668779898)]
jvm面试专题与解析
- JVM 由哪些部分组成?
- JVM 内存划分?
- Java 的内存模型?
- 引用的分类?
- GC什么时候开始?
JVM面试专题解析与拓展!
[外链图片转存中…(img-H3j4vuXC-1714668779898)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!