I would say that the reason Spring favors XML over Java is that the two languages are for two different tasks. Java is a programming language. Its purpose is to describe algorithms, programs, control flow, etc. If deducing the structure of your program requires complex control flow, Java would be a good choice.
XML is fundamentally different. It is not a programming language. It is a way to describe ordered data, like a cookbook or a vector graphic. If the organization and interdependencies of your program's system are static values, then XML might be an appropriate place to put them.
I would argue that your configuration stuff should generally not be in Java for the same reason that a cookbook should not be in Java. In fact, I could make the same conversion:
<book>
<chapter>It was the best of times, it was the worst of times</chapter>
</book>
public static void main(String[] args)
{
String chapter1 = BookXMLParser.loadChapter(1);
System.out.println(chapter1);
}
could obviously also be done entirely in Java:
public static void main(String[] args)
{
String chapter1 = "It was the best of times, it was the worst of times");
System.out.println(chapter1);
}
Now, obviously, this is a ridiculous example. Books are hundreds of pages long. It would be silly to keep them in Java code. However, I would make the same argument for Spring configuration. One of my largest programs has spring XML that totals to many thousand lines.
Of course, there's definitely something to be said in favor defining this stuff in Java. Most especially, IDEs would be able to provide additional help more easily about which classes are using what, and other static analysis tools would be a little better at analyzing your code for problems as well.
Then again, there are also some downsides. Allowing you to do this configuration in Java allows the programmer to do all sorts of nasty things that are significantly harder to achieve in XML, like this:
bean1.setName("fred");
if( System.currentTimeMillis() > 1234567890l ) {
//Automatically use new feature after next Thursday
bean1.setNewFeature(1);
} else if( x > 17 ) {
switch(y) {
case POTATO:
bean1.setNewFeature(0);
break;
case POTAHTO:
bean1.setNewFeature(1);
case WHO_COULD_ASK_FOR_ANYTHING_MORE_FALLTHROUGH:
bean1.setFoo(bar);
break;
default:
baz? bean1.setBar(baz) : if(17 > t)
{ bean1.setNewFeature(q) } else {
throw new RuntimeException("That's odd...");
}
}
}
Well, you get the point. Your code obviously won't start out that bad, but you'll be tempted to use an if statement somewhere, and then you'll use another, and then another....