Do Service and DAO Layers Need Interfaces? When to Use Them in Spring Projects
This article examines whether every Service and DAO class in a Spring‑based backend should implement an interface, discusses the three traditional reasons for using interfaces, explains why they often do not hold up, and proposes practical structuring alternatives for single‑ and multi‑implementation scenarios.
Recently I saw a discussion in a technical group asking whether every Service and DAO class really needs an interface. My earlier answer was simply "it depends".
After reviewing projects that use dependency‑injection frameworks like Spring, I concluded that interfaces are unnecessary when such frameworks are present.
Below are the three classic reasons people give for adding interfaces to Service and DAO layers:
It allows upper layers (e.g., Controllers) to be coded before the lower‑level logic is implemented.
Spring’s default AOP implementation relies on dynamic proxies, which require interfaces.
It enables multiple implementations of a Service.
In practice, none of these reasons are compelling:
1. The first reason promotes interface‑driven development, which is useful only when different teams work on separate modules. Most projects are organized by functional modules, and a single developer often handles the whole stack from Controller to DAO, making extra interfaces just extra work.
If you need to develop the upper layer before the lower one, you can simply create empty methods in the lower‑level class.
2. Spring can use CGLIB instead of JDK dynamic proxies, so interfaces are not required for AOP.
3. Multiple implementations are rarely needed; when they are, other techniques can replace the need for an interface.
Below is a typical three‑layer project structure:
Controller
Service
Dao
If you do need multiple implementations, the structure might look like this:
Controller
Service Interface package impl package (first implementation)
Dao
Two ways to handle multiple implementations were described:
Add a new package under Service and configure the new implementation as the injected bean.
Create a completely new Service module (different package or class name) and configure it as the injected bean.
The first approach is simpler because it only concerns package organization; the second adds module‑level complexity and may introduce unused code.
A hybrid solution is to separate the interface and its implementations into distinct modules, then let the build configuration choose between ServiceImpl and ServiceImpl2 at packaging time. This keeps the package structure identical while allowing easy swapping.
If you remove the interface module entirely, you end up with two concrete Service classes (Service1 and Service2) that can be selected via dependency configuration. This works but loses the compile‑time contract that interfaces provide.
In summary, interfaces are useful mainly when a project requires many implementations; otherwise, they add unnecessary overhead.
Feel free to share your own thoughts on whether Service layers should have interfaces.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.