When you've got a complex graph of objects and dependencies between them, DI can easily take care of instantiating an A and feeding it to a B that requires an A and so on and so on.
In our projects we'll have a DebuggerFooImpl, a MockFooImpl, and a ProdFooImpl. Spring's AppConfig classes then can create the proper object at startup based on environment profiles and no consumers have to do any more than ask for the Foo object to be injected into them, isolating them from any environment awareness/coupling.
There are other benefits from DI as well, but the above at the low hanging fruit, isolating the complexity of object creation from the object's consuming classes.
In our projects we'll have a DebuggerFooImpl, a MockFooImpl, and a ProdFooImpl. Spring's AppConfig classes then can create the proper object at startup based on environment profiles and no consumers have to do any more than ask for the Foo object to be injected into them, isolating them from any environment awareness/coupling.
There are other benefits from DI as well, but the above at the low hanging fruit, isolating the complexity of object creation from the object's consuming classes.