Regarding abstraction vs. concretion, I think that programming against the interface vs. the concrete implementation is a good thing. This enables to replace the concrete implementation with a mock for testing. OTOH in my experience you seldom need more than one concrete implementation, and if you do, you have a strategy and their implementations. For those cases you need to have separate configurations anyway, each based on a certain case. As you are mentioning Springs @Autowired here, you could create @Configuration s for these cases, which would enable you to define the required dependency externally. Each of these could be enabled by a @Profile when appropriate. I'm guessing that you mean to be able to very easily shoot yourself in the foot by overusing it, which I completely agree with. But most of the time it saves me personally from writing the boilerplate code of object creation and composition, which I think is good