At the class level, it is easy.
'Dependency Injection' simply answers the question "how will I find my collaborators" with "they are pushed at you - you don't have to go and get them yourself". (It is similar to - but not the same as - 'Inversion of Control' where the question "how will I order my operations over my inputs?" has a similar answer).
The only benefit that having your collaborators pushed at you is that enables client code to to use your class to compose an object graph which suits its present need ... you have not arbitrarily pre-determined the shape and mutability of the graph by privately deciding the concrete types and life-cycle of your collaborators.
(All those other benefits, of testability, of loose coupling, etc, follow largely from the use of interfaces and not so much from the dependency-injection-ness, although DI does naturally promote the use of interfaces).
It is worth noting that, if you do avoid instantiating your own collaborators, your class must therefore get its collaborators from a constructor, a property, or a method-argument (this latter option is often overlooked, by the way ... it does not always make sense for a class' collaborators to be a part of its 'state').
And that's a good thing.
At the application level ...
So much for the per-class view of things. Let's say you have a bunch of classes which follow the "do not instantiate your own collaborators" rule, and wish to make an application from them. The simplest thing to do is to use good old code (a really useful tool for invoking constructors, properties, and methods!) to compose the object graph you want, and throw some input at it. (Yes, some of those objects in your graph will themselves be object-factories, which have been passed around as collaborators to other long-lived objects in the graph, ready for service ... you can't pre-construct every object!).
... your need to 'flexibly' configure your app's object-graph ...
Depending on your other (non-code-related) objectives, you might want to give the end-user some control over the object graph thus deployed. This leads you in the direction of a configuration scheme, of one sort or another, whether it be a text file of your own design with some name/value pairs, an XML file, a custom DSL, a declarative graph-description language such as YAML, an imperative scripting language such as JavaScript, or something else appropriate to the task at hand. Whatever it takes to compose a valid object graph, in a way that meets the needs of your users.
... may be a significant design force.
In the most extreme circumstance of that type, you could elect to take a very general approach, and give end users a general mechanism for 'wiring up' the object-graph of their choosing and even allow them to provide concrete realizations of interfaces to the runtime! (Your documentation is a gleaming jewel, your users are very smart, familiar with at least the coarse outline of your application's object graph, but don't happen to have a compiler handy). This scenario can theoretically occur in some 'enterprise' situations.
In that case, you probably have a declarative language which allows your users to express any type, the composition of an object graph of such types, and a palette of interfaces which the mythical end-user can mix and match. To reduce the cognitive load on your users, you prefer a 'configuration by convention' approach, so that they only have to step in and over-ride the object-graph-fragment of interest, instead of wrestling with the whole thing.
You poor sod!
Because you didn't fancy writing up all that yourself (but seriously, check out a YAML binding for your language), you are using a DI framework of some kind.
Depending on the maturity of that framework, you may not have the option of using constructor-injection, even when it makes sense (the collaborators don't change over the lifetime of an object), thereby forcing you to use Setter Injection (even when collaborators don't change over the lifetime of an object, and even when there is not really a logical reason why all concrete implementations of an interface must have collaborators of a specific type). If so, you are currently in strong-coupling hell, despite having diligently 'used interfaces' throughout your code-base - horror!
Hopefully though, you used a DI framework which gives you option of constructor injection, and your users are only a bit grumpy at you for not spending more time thinking about the specific things they needed to configure and giving them a UI more suited to the task at hand. (Although to be fair, you probably did try to think of a way, but JavaEE let you down and you had to resort to this horrible hack).
Bootnote
At no point are you ever using Google Guice, which gives you the coder a way to dispense with the task of composing an object-graph with code ... by writing code. Argh!