I understand benefits of dependency injection itself. Let\'s take Spring for instance. I also understand benefits of other Spring featureslike AOP, helpers of different kind
For myself one of the main reasons to use an IoC (and make use of external configuration) is around the two areas of:
Testing
If you split your testing into 3 scenarios (which is fairly normal in large scale development):
What you will want to do is for the last two test scenarios (Integration & Black box), is not recompile any part of the application.
If any of your test scenarios require you to change the configuration (ie: use another component to mimic a banking integration, or do a performance load), this can be easily handled (this does come under the benefits of configuring the DI side of an IoC though.
Additionally if your app is used either at multiple sites (with different server and component configuration) or has a changing configuration on the live environment you can use the later stages of testing to verify that the app will handle those changes.
Production
As a developer you don't (and should not) have control of the production environment (in particular when your app is being distributed to multiple customers or seperate sites), this to me is the real benefit of using both an IoC and external configuration, as it is up to the infrastructure/production support to tweak and adjust the live environment without having to go back to developers and through test (higher cost when all they want to do is move a component).
Summary
The main benefits that external configuration of an IoC come from giving others (non-developers) the power to configure your application, in my experience this is only useful under a limited set of circumstances:
In practice I've found that even when developing something that you do have control over the environment it will be run on, over time it is better to give someone else the capabilities to change the configuration:
Note: Application refers to the complete solution (not just the executable), so all files required for the application to run.
Any time you can change your code to data you're making a step in the right direction.
Coding anything as data means that your code itself is more general and reusable. It also means that your data may be specified in a language that fits it exactly.
Also, an XML file can be read into a GUI or some other tool and easily manipulated pragmatically. How would you do that with the code example?
I'm constantly factoring things most people would implement as code into data, it makes what code is left MUCH cleaner. I find it inconceivable that people will create a menu in code rather than as data--it should be obvious that doing it in code is just plain wrong because of the boilerplate.
In the .NET world, most of IoC frameworks provide both XML and Code configuration.
StructureMap and Ninject, for example, use fluent interfaces to configure containers. You are no longer constrained to use XML configuration files. Spring, which also exists in .NET, heavily relies on XML files since it is his historical main configuration interface, but it is still possible to configure containers programmatically.
You can slot in a new implementation for girlfriend. So new female can be injected without recompiling your code.
<bean id="jane" class="foo.bar.HotFemale">
<property name="age" value="19"/>
</bean>
<bean id="mary" class="foo.bar.Female">
<property name="age" value="23"/>
</bean>
<bean id="john" class="foo.bar.Male">
<property name="girlfriend" ref="jane"/>
</bean>
(The above assumes Female and HotFemale implement the same GirlfFriend interface)
Often, the important point is who is changing the configuration after the program was written. With configuration in code you implicitly assume that person changing it has the same skills and access to source code etc as the original author had.
In production systems it is very practical to extract some subset of settings (e.g. age in you example) to XML file and allow e.g. system administrator or support personal to change the value without giving them the full power over source code or other settings - or just to isolate them from complexities.
Spring also has a properties loader. We use this method to set variables that are dependant on the environment (e.g. development, testing, acceptance, production, ...). This could be for example the queue to listen to.
If there is no reason why the property would change, there is also no reason to configure it in this way.