Spring 里 Service 层分成接口+Impl 的好处是什么?
分开写感觉很累赘,为什么很多人这么选择?
为什么不直接用一个 Service 类实现
分开写感觉很累赘,为什么很多人这么选择?
为什么不直接用一个 Service 类实现
用接口的好处是我无需关注他是如何实现的,你一个接口可以有多重实现类 , 后期方便维护, 屏蔽底层实现细节
不好的地方是 代码量变多了
我一个功能接口,有三套逻辑,根据类型去判断到底用哪套逻辑。不同逻辑就是不同实现类
所以我要用接口。
再使用策略模式+spring 的注入机制。我调用层只注入接口就可以。
但很多时候,还是一个接口一个实现类。
有很多同事都习惯把不同逻辑的全放到一个实现类。各种 if 判断……
只是国内的架构师,做软件设计的角色,没有起到相应的作用,其根源也是国内的公司都是猴急一样的做项目,没有回到软件系统设计本身,各种文档,各种形式很足,做出来的东西一团糟。
对于复杂的业务流程,都是可以完全接口调用方式设计,完全先不管具体实现,用一个 Dummy 实现先去验证设计上的逻辑是否能够合理。
我在国内公司呆那么多年,从来没有哪个公司会让你花时间写 POC 去验证一套流程的合理性。如果做国外的产品项目就完全不一样,你有很多机会去想如何才能做到真正的逻辑上的解耦。
https://github.com/hantsy/spring-reactive-jwt-sample/tree/master/src/test/java/com/example/demo
实际上很多业务的接口都是一对一的,不会复用,也不会留足时间给你慢慢先思考再上线。。更多的是 CRUD 莽代码。
但自己还是要知道这种编程范式和带来的优势的(上都说过了),用不用那是另外一回事。
2. 如果你实际编程中由于某些原因想替换掉其中一个方法的话,可以替代 @Lookup 注解,直接换另一个实现类。
3. 还有一个是 RPC 调用,引入接口即可,然后通过 Annotation*BeanPostProcessor 之类的将接口装饰成具体代码调用。例如 @DubboService 这种。你定义入参就行了,不用关心其具体的实现,你在其他 Service 或者 Controller 直接构造方法注入就 ok 了。
服务之间交互通过轻量协议( Http,Message Broker,gRPC,RSocket 等)定义。
繁琐,堆砌,复用说不上,难看才是真的
现在只剩 XXXController,其他的除非确实必要,否则一概不写
Short answer: No.
If you want the long answer, here it is:
One of the main interests of using Spring is AOP. This is the technology that allows Spring to add new behaviors on top of your Beans: for instance, this is how transactions or security work.
In order to add those behaviors, Spring needs to create a proxy on your class, and there are two ways of creating a proxy:
If your class uses an interface, Spring will use a standard mechanism provided by Java to create a dynamic proxy.
If your class doesn’t use an interface, Spring will use CGLIB to generate a new class on the fly: this is not a standard Java mechanism, but it works as well as the standard mechanism.
Some people will also argue that interfaces are better for writing tests, but we believe we shouldn’t modify our production code for tests, and that all the new mocking frameworks (like EasyMock) allow you to create very good unit tests without any interfaces.
So, in the end, we find that interfaces for your Service beans are mostly useless, and that’s why we don’t recommend them (but we leave you with the option to generate them!).
“如果做国外的产品项目就完全不一样,你有很多机会去想如何才能做到真正的逻辑上的解耦。”
国外真的这样么?
@hantsy #27 俺遇到的基本都是:设计和测试是最不给时间的,每天都是写写写,然后早会汇报完成了多少多少。
你要是连着几天汇报在搞设计,上面会认为你在没有任何产出。。。
有时真不知道这些“上面”当初是如何写软件的。难道他们也不是过来人么?难道他们体会不到这东西也要设计,也要 demo 的么。。。
1. 贫血模型:从 dao 层查出来的只是数据,而且是和具体 dao 层字段绑定的格式(如 mysql )
2. 所有的业务都在 service 层( service 中各种对贫血模型字段的判断和处理)
因为”业务”本身就不是抽象的,不需要多实现,所以,导致的就是 service 接口和对应一个 service impl 这种鸡肋的形式存在。你想想,同一 service 接口,你还能有其它什么实现么?
真正需要接口的是需要抽象时,需要和具体实现无关时,如
一个接口 UserRepository 表示用户数据仓库
而实现可以是
FileUserRepository
DBUserRepository
XXXUserRepository
这样多实现是有意义的。
而业务都写在 service 类里,那么业务的多实现指的又是什么呢?
造成主的困惑原因,可能就是”前人都这样写,那我也这样写吧”
于是,就这样了
对于很多人用类,接口跟 PHP4 的函数没差别,只是堆代码,没有从语言和软件的角度考虑为什么有接口和类这些不同的玩意。
我说过,我以前很多时候写 POC,比如银行对账的一个简单的流程,将请求类,响应类,各种异常路径包装成异常,所有的行为用接口来描述。用简单的 Dummy/Fake 实现类(伪数据填充出来的),用测试验证一个流程中各接口的合理性,一步步连接起来是否通畅,是否所有异常路径都是可以顾及到。
经过反复讨论过后,再把接口抽出来 ,切换到真实场景去实现( Bank Credit,Stripe 等)。
比如你想写个缓存小组件,可以基于 memory/redis ,这时你定义一个接口就有用了…