Understand why large Java systems drift toward Service Locator, where that helps, and where explicit injection scales better.
Large Java applications do create pressure for some form of central wiring. That pressure is real. The mistake is assuming the only answers are “manual wiring everywhere” or “let every class pull dependencies from a locator.”
Teams usually adopt Service Locator for one of these reasons:
All of those pressures are understandable. None of them automatically makes lookup the best long-term model.
Large systems need clarity about:
Constructor injection and application bootstrap usually make those concerns easier to inspect. Service Locator centralizes access, but it often makes dependency edges less visible.
In a large Java codebase, Service Locator is more defensible at the edge:
At those boundaries, “lookup” is part of the actual domain or infrastructure model. Inside ordinary domain and application services, explicit injection is usually easier to reason about.
In small code, hidden dependencies are annoying. In large code, they become expensive:
That is why large codebases benefit from more explicitness, not less.
If a large legacy system already uses Service Locator heavily, the best move is often staged, not ideological:
This turns the locator into a compatibility layer instead of the central design language of the system.
When reviewing dependency management in a large Java application, ask:
Large applications do not need fewer boundaries. They need more visible ones.