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, evaluates the common arguments for using interfaces, explains why they often do not hold up, and proposes practical structuring and development approaches for projects that may or may not need multiple implementations.
Recently a question surfaced on Toutiao: "Is it necessary to add an interface to every Service and DAO class?" The initial answer was "it depends," but this article dives deeper.
If a project uses a dependency‑injection framework like Spring, interfaces are not strictly required.
Three typical reasons people give for adding interfaces are:
It allows writing upper‑layer code (e.g., Controllers) before the lower‑layer logic is implemented.
Spring’s default AOP implementation relies on dynamic proxies, which need interfaces.
It enables multiple implementations of a Service.
All three reasons are weak when a DI framework is present.
First reason – writing code before the implementation exists – is useful only when different teams develop separate layers. In most projects, development is organized by functional modules, and a single developer often handles the whole flow from Controller to DAO, making extra interfaces unnecessary.
If you still need to code the upper layer before the lower one, you can simply create empty methods in the lower‑level class.
A recommended bottom‑up coding workflow is:
Write the Controller logic first, inserting Service calls as needed.
Let the IDE generate the missing Service classes and methods, marking them with TODO.
After all classes and methods are generated, fill in the business logic based on the TODOs.
Second reason – Spring’s AOP uses dynamic proxies – can be bypassed by configuring CGLIB, which does not require interfaces.
Third reason – multiple Service implementations – is rarely needed; when it is, other techniques (e.g., configuration‑based bean selection) can replace interfaces.
Typical project layer structure is:
Controller
Service
Dao
When multiple implementations are required, two common structures appear:
Keep a single Service package with an interface and separate implementation packages (impl, impl2).
Create separate Service modules (Service and Service2), each with its own implementation.
The first approach is simpler, but both introduce redundant code.
A hybrid solution is to separate the interface and its implementations into distinct modules, then adjust packaging so that only one implementation module is included at build time, allowing the same package layout for both.
If the interface module is removed entirely, the project can still work with two Service implementations (Service1 and Service2) selected via module dependencies, but the lack of a strong contract makes IDE assistance and compile‑time checks harder.
In summary, interfaces are useful when a project truly needs multiple implementations or strict contracts; otherwise, with modern DI frameworks, they add unnecessary overhead.
Feel free to share your thoughts in the comments.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
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.
