In this current post monolith, micro-service world, most java applications remain very maintainable though.
You can't tell by reading it either, because it's all dynamic: all of the autoconfigurations create beans conditionally only if other beans of that type aren't defined, if certain classes are present on the classpath, if particular values are defined in the configuration that's written in magical self-transforming YAML, or all three. The only way I've found is to breakpoint at the point where something is wired in to see what the concrete class is, then breakpoint again in the constructor of that class to find where it's being constructed from, so you have to restart your application and run the (slow) spring boot startup twice for each thing you care about. And even that doesn't always work because spring encourages doing AOP with bytecode-manipulation-based proxies.
An alternative would be to have a Main method construct all of the objects and pass them into each other, but @Autowired takes care of that for you.
The argument is that most of your services will be global-ish singletons, and so the details of which services are used from which other services are ceremony rather than business logic; if you've made a code change that means service A now calls service C instead of service B, you want the diff to be about the actual code change in A rather than the plumbing of where it's getting service C from. Since there are problems with language-level singletons (e.g. testability) you want to use plain objects passed to the constructor, but since 99.9% of the time the FooService is always going to be the FooServiceImpl, you don't want the trouble of explicitly wiring it all up yourself. I don't necessarily think Spring is worth it, but wiring by hand certainly does involve writing a lot of code that's more or less irrelevant to your actual business logic.
> At least tools (including IDE) can look for method calls, annotation strings not so much.
Actually one of the things that makes Spring almost tolerable is that IDEs generally do have integration with it, and so "find references" will work properly even for things that are reflectively instantiated by Spring.
(That only applies as long as your wiring is "static" though. With Spring Boot's conditional bean annotations all that goes out of the window and you have no hope of understanding where anything is coming from or where anything is used).
Fixed it for you.