Spring Boot中的业务层(Service)是否要创建接口,以及如果Service有多个实现类,如何让Spring知道该注入哪个Impl类的分析

参考文档:Spring中 如果该Service有多个实现类,它怎么知道该注入哪个ServiceImpl类?
关于Spring Boot中的业务层(Service)是否要创建接口的分析

一、Spring Boot中的业务层(Service)是否要创建接口?

借助Spring Boot框架开发web项目时,在业务层(Service)这一部分,标准做法是:定义一个接口,然后再一个或多个类去实现。那么疑问来了:

为什么我们要维护两份同构代码,而不直接使用一个类呢?

不创建接口,通过把业务实现类直接通过注解@Autowired注入控制层Controller,也一点不耽误功能的实现啊,那么我为什么还要创建接口?

网上大部分回答都是说什么面向对象的解耦云云,引经据典,说得都很好,然而,都没有从根本上回答我们关心的问题:为什么要用接口?

业务层(Service)中为什么一定要用接口,不用行不行?回答:不是必须要使用接口,但强烈建议使用接口。

情景1: 在开源框架中有很多这种情况,就是某个功能支持用户自定义扩展.说白了,它提供了一个接口,我们只需要实现这个接口,把我们自己的实现逻辑补上,就可以让框架按照我们的逻辑来执行.问题来了,框架的作者并不知道我们的实现类是什么,如果不定义一个接口,那么要如何在框架中调用我们的实现类呢?

情景2: 我和同事分别做项目的2个不同功能模块,但是同事的功能中却需要调用我这头实现的部分逻辑.为了让他有一个"占位符"可用,我是不是应该快速的写个接口扔给他呢?

情景3: 一个适配器功能,或是说一个简单的工厂类,如果没有定义接口,那么面对众多实现类,要如何统一操作呢?

情景4: 想让项目的代码符合某种"规范",但是又不可能看着别人写代码吧,那好办,先出一套接口,然后你们就看着办~

情景5: java中没有多继承,但是可以多实现接口,那么就有一件很有趣的事情了,一个实现类可以实现多个接口,然后此时接口可以有选择的暴露实现类的部分方法,做到"窄化"实现类功能的目的。

当然例子还有很多,这些情况其实可以说是接口好处的体现,所以java有面向接口编程的建议,但是说回Service层一定要有接口吗?那到未必,因为说到底,多一个接口仅仅是扩展性和某些情况下有优势,但是是否会用到接口的便利性,不确定的情况下我们未必一定要为"可能"买单,只是多写那几行代码,付出一点就可能避免"未来"的大"麻烦",何乐而不为!?

下面简单列出Spring Boot中业务层(Service)的创建步骤及应用:

  1. 接口及实现类命名方式,接口XXXService,实现类:XXXServiceImpl。

  2. 实现类XXXServiceImpl需添加注解@Service,并指明名称,如@Service("companyService")

  3. 在实现类中,通过注解@Autowired,注入数据仓库层Repository接口;

当实现的接口涉及数据库数据的删除或修改时,方法上一定要添加注解@Transactional,否则会执行不成功。

二、 如果该Service有多个实现类,它怎么知道该注入哪个ServiceImpl类?

  1. 为每个service的impl都指定名称(使用@Service(“名称”)

  2. 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();
    }
}

以上

你可能感兴趣的:(Spring Boot中的业务层(Service)是否要创建接口,以及如果Service有多个实现类,如何让Spring知道该注入哪个Impl类的分析)