一、Spring Boot中的业务层(Service)是否要创建接口?
借助Spring Boot框架开发web项目时,在业务层(Service)这一部分,标准做法是:定义一个接口,然后再一个或多个类去实现。那么疑问来了:
为什么我们要维护两份同构代码,而不直接使用一个类呢?
不创建接口,通过把业务实现类直接通过注解@Autowired
注入控制层Controller,也一点不耽误功能的实现啊,那么我为什么还要创建接口?
网上大部分回答都是说什么面向对象的解耦云云,引经据典,说得都很好,然而,都没有从根本上回答我们关心的问题:为什么要用接口?
业务层(Service)中为什么一定要用接口,不用行不行?回答:不是必须要使用接口,但强烈建议使用接口。
情景1: 在开源框架中有很多这种情况,就是某个功能支持用户自定义扩展.说白了,它提供了一个接口,我们只需要实现这个接口,把我们自己的实现逻辑补上,就可以让框架按照我们的逻辑来执行.问题来了,框架的作者并不知道我们的实现类是什么,如果不定义一个接口,那么要如何在框架中调用我们的实现类呢?
情景2: 我和同事分别做项目的2个不同功能模块,但是同事的功能中却需要调用我这头实现的部分逻辑.为了让他有一个"占位符"可用,我是不是应该快速的写个接口扔给他呢?
情景3: 一个适配器功能,或是说一个简单的工厂类,如果没有定义接口,那么面对众多实现类,要如何统一操作呢?
情景4: 想让项目的代码符合某种"规范",但是又不可能看着别人写代码吧,那好办,先出一套接口,然后你们就看着办~
情景5: java中没有多继承,但是可以多实现接口,那么就有一件很有趣的事情了,一个实现类可以实现多个接口,然后此时接口可以有选择的暴露实现类的部分方法,做到"窄化"实现类功能的目的。
当然例子还有很多,这些情况其实可以说是接口好处的体现,所以java有面向接口编程的建议,但是说回Service层一定要有接口吗?那到未必,因为说到底,多一个接口仅仅是扩展性和某些情况下有优势,但是是否会用到接口的便利性,不确定的情况下我们未必一定要为"可能"买单,只是多写那几行代码,付出一点就可能避免"未来"的大"麻烦",何乐而不为!?
下面简单列出Spring Boot中业务层(Service)的创建步骤及应用:
- 接口及实现类命名方式,接口XXXService,实现类:XXXServiceImpl。
- 实现类XXXServiceImpl需添加注解
@Service
,并指明名称,如@Service("companyService")
; - 在实现类中,通过注解
@Autowired
,注入数据仓库层Repository接口;
当实现的接口涉及数据库数据的删除或修改时,方法上一定要添加注解@Transactional
,否则会执行不成功。
二、 如果该Service有多个实现类,它怎么知道该注入哪个ServiceImpl类?
- 为每个service的impl都指定名称(使用
@Service(“名称”)
) - Controller中注入service的时候使用名称来指定注入哪一个:
(1)@Autowired
按类型进行注入
@Autowired
@Qualifier("名称")
(2)@Resource
按名称进行注入
@Resource(name="名称")
例子:
service接口:
public interface HumanService {
public String name();
}
接口Impl实现类:
@Service("teacherService")
public class TeacherServiceImpl implements HumanService {
@Override
public String name() {
System.out.println("teacher");
return "teacher";
}
}
@Service("doctorService")
public class DoctorServiceImpl implements HumanService {
@Override
public String name() {
System.out.println("doctor");
return "doctor";
}
}
controller层:
@RestController
public class HumanController {
// @Resource(name="doctorService")
@Autowired
@Qualifier("teacherService")
private HumanService humanService;
@RequestMapping("/name")
public String name(){
return humanService.name();
}
}
以上