为什么在服务和dao层中总是有单个实现接口?

我已经/看过一些spring-hibernate Web应用程序项目,它们具有与实际服务和dao类一样多的接口。

我一直认为这两个是这些单一实现接口的主要原因:

  1. Spring可以将实际实现连接为给定类中的依赖项(松散耦合)

    public class Person { @Autowired private Address address; @Autowired private AccountDetail accountDetail; public Person(Address address, AccountDetail accountDetail) { // constructor 
  2. 在进行unit testing时,我可以创建模拟类并单独测试类。

     Address mockedAddress = mock(Address); AccountDetail mockedAccountDetail = mock(AccountDetail); Person underTestPerson = new Person(mockedAddress, mockedAccountDetail); // unit test follows 

但是,最近,我意识到:

Spring可以将具体实现类连接为依赖项:

 public class Person { @Autowired private AddressImpl address; @Autowired private AccountDetailImpl accountDetail; public Person(AddressImpl address, AccountDetailImpl accountDetail) { // constructor 

像EasyMock这样的模拟框架也可以模拟具体的类

 AddressImpl mockedAddress = mock(AddressImpl); AccountDetailImpl mockedAccountDetail = mock(AccountDetailImpl); Person underTestPerson = new Person(mockedAddress, mockedAccountDetail); // unit test follows 

此外,根据这个讨论,我认为总结是在单个应用程序中,接口大多是过度使用可能超出惯例或习惯。 它们通常在我们与另一个应用程序接口的情况下最有意义,例如世界上许多应用程序使用的slf4j。 在单个应用程序中,类几乎与接口一样是抽象。

所以,我的问题是为什么我们仍然需要接口,然后有单个实现,如* ServiceImpl和* DaoImpl类,并不必要地增加我们的代码基本大小。 在模拟我不了解的具体课程时是否存在一些问题。

每当我和我的队友讨论这个问题时,我得到的答案就是实现基于接口的服务和dao类是每个人都遵循的设计 – 他们提到了春季最佳实践,OOP,DDD等。但我仍然没有在孤立的应用程序中拥有如此多的接口背后有一个实用的理由。

接口有更多优点 – 如在代理中。 如果您的类实现了接口,则默认情况下将为AOP使用JDK动态代理。 如果直接使用实现,则会通过使proxy-target-class = true强制使用CGLIB代理。 与JDK代理不同,它们需要字节代码操作。

在这里阅读更多相关信息。

阅读另一个讨论, 了解更多信息使用接口(Java EE或Spring和JPA)的原因。

这是一个非常有争议的话题。 简而言之,没有 – 至少对你而言,开发人员。

在EJB2世界中,Home和Remote接口是必须的,而且正是出于某种原因@AravindA提到:代理。 安全性,远程处理,池化等都可以包含在代理中,并严格在标准库中提供所请求的服务(如在DynamicProxy )。

现在我们有javaassistcglib ,Spring(Hibernate,EJB3,如果你愿意的话)完全能够像框架开发人员喜欢的那样检测你的类。 问题是,他们做的是一件非常讨厌的事情:他们通常会要求你添加一个无参数的构造函数.-等等,我在这里有参数?-Nevermind,只需添加构造函数。

所以接口就是为了保持你的理智。 但是,奇怪的是,对于具有适当构造函数的类而言,无参数构造函数对我来说并不合适,对吧? 事实certificate(我应该阅读规范,我知道)Spring创建了类的接口的function等价物:没有(或忽略)状态的实例和所有被覆盖的方法。 所以你有一个“真正的”实例和一个“假接口”实例,虚假接口的作用是什么,它为你提供所有的安全/事务/远程魔术。 很好,但很难理解,如果你没有将它拆开,看起来像一个bug。

此外,如果您碰巧在您的类中实现了一个接口,(至少某些版本)Spring突然决定您只代理此接口,并且应用程序无法正常工作。

因此,到目前为止,原因是,安全和理智。 有理由说这是一个很好的做法 – 但是从你的post中,我看到你已经阅读了所有这些。 我今天能看到的最重要的原因是WTH /分钟指标,特别是如果我们谈论你的项目的新人。