If you have ever used Struts2 properly, you would know that: a. it is really just Web Works (the end result of a laudable effort to "fix" the h-o-r-r-i-b-le Struts1 API) ; b. it has DI, Interceptors; c. it's API is actually more streamlined than that of Spring MVC.
For example, the Spring ThrowawayController (notably in a completely different object hierarchy than Spring's other Controllers) is almost as streamlined as a Struts2's standard Action. Both have a parameterless execute() method - Struts2 returns a "transparent" String, while Spring's Controller returns a ModelAndView (which is certainly not as "transparent").
By the way, can anyone explain (does anyone care) that the parameters for a ModelAndView() are bass-ackwards, mandating that the view object preceed the model?
In Struts2, you get a powerful (open standards-based) language called OGNL, something called a ValueStack, and Interceptors. These are noteworthy because they, in aggregate, allow for "convention-over-configuration", and make Struts2 superior to Spring MVC.
Anther thing about Spring rankles: the "decoupling" that happens in Java objects when using Spring indeed happens - trouble is that the objects are still interdependent, instead now the interdenendencyis expressed in XML (and a recompile is needed if the XML mappings change)! You also use bytecode instrumentation (via the container) to accomplish the "magic". And really, if dependent class A has a setter for class B, can it really be said that it does not know about (have a dependencey upon) class B? Be honest.