I Don't Get Spring
Preface: Please note that this entry is well over a year old. I've since addressed all of my concerns with a new framework named Guice. Try it out. You'll find a direct comparison between Guice and Spring here.
By "Spring" I mean the Spring Framework, specifically the dependency injection container. First off, I mean no offense to Rod et al (you're all good people), but frankly I haven't been able to get my head around your framework. Even worse, I've noticed what I consider to be a dangerous and blind increase in the rate of Spring adoption. I've yet to read a critical article or book on Spring. It seems like everyone loves Spring except me; am I missing something? Maybe Spring adoption is a knee-jerk reaction to J2EE. "J2EE is bad, and the Spring guys say their stuff is better, so Spring must be good." It doesn't work that way.
Second, I'm talking about Spring specifically, not dependency injection. I love dependency injection, and I follow the patterns every day. Good riddance to service locators!
I can't tell you how many times I've had a developer tell me, "I used Spring on my last project and it worked really well," without being able to articulate what exactly they like about it or how it actually helped them. So far as I can tell, they like setter injection because it makes their code more flexible and testable, but that doesn't necessitate Spring. I guess for those who don't have the "dependency injection" mindset ingrained, using a framework that encourages (forces?) you to do the right thing helps. This encouragement doesn't outweigh the laundry list of negative impacts Spring has on your code though.
The Spring folks openly snub their noses at J2EE, but from what I can tell Spring isn't exactly lightweight and simple either. The Javadocs are unnecessarily overwhelming. Does all of this really belong in a user API? At least J2EE cleanly separates API from implementation. Spring advocates tout that Spring doesn't "touch" your code, i.e. you don't have to implement any Spring-specific interfaces (with the exception of life-cycle interfaces, etc.). News flash: the XML configuration is my code, and from what I can see it often ends up constituting a lot of code, all of which is Spring-specific.
Why would I want to express all of my dependencies in XML? Do I use Spring for all of my objects or just the coarse-grained ones? From what I can tell, neither the Spring documentation nor any Spring articles give any solid advice in this area. Am I supposed to use Spring to create all of my objects? Do we not like Java? I want to validate this stuff at compile time, load time at the latest, not while I'm running my code. Does Spring support that?
Obviously I want to load some dependencies like JDBC driver implementations dynamically (i.e. without requiring compile time checking), but these make up a small fraction of the dependencies in my system. What about the rest, the majority? I'm using a strongly typed language; why would I want to throw all of this perfectly good type information away? If I wanted that, I'd use Ruby. Doesn't the Spring configuration start to look suspiciously like writing Java code in XML? Is Spring for developers who aren't comfortable with Java? I'm not convinced adding a layer of XML makes things any simpler.
Back to dependencies on Spring APIs; don't I have to call the container to create my first object (assuming the rest of the Spring-managed objects in the graph are injected)? I want some way to check that the object I'm requesting is the right type at compile time. I don't want to cast. Ever. Do I really even need a container? In Spring you look up objects using a unique ID. I assume most developers define a String constant for the ID in their Java code. That doesn't help me keep the ID value in my java code in sync with the value in my XML. Why do I need both this ID and a container? Why use two objects when one will do? Should we really group all of this information together into a container? Do Java packages and classes not suffice?
It bothers me that I have to reference Spring implementation classes in my XML configuration. I don't care about the plumbing. In Spring's defense, I've heard they have so more concise, domain-specific XML coming in 2.0, but I haven't seen it yet. Why didn't this come up sooner?
What's with all the inheritance? And the permutation upon permutation of long winded class names? Not my style.
Where's the JDK 1.5 generics support? I know you have a lot clients running 1.4 and even 1.3, but that's what branching is for. Generics have opened the doors to all sorts of new possibilities for frameworks like this. They're my favorite new JDK feature. Embrace them.
Have you ever looked at how much work Spring does every time you create an object? I want fewer instanceof
s at runtime and more Class.isAssignableFrom()
s at load time. Not that the internal implementation matters that much to end users, but it works as a litmus test for the quality of the rest of the framework. A good refactoring to the bean creation pipeline would result in easier to follow and more performant code and would enable reuse without resorting to so much inheritance.
What's with auto-wiring? Does anyone actually use that, or is just another notch in the feature headboard?
How does Spring handle scopes? I heard it will finally support HTTP request and session scopes in version 2.0. I was surprised to here that it didn't support this already. What have Spring users been doing this whole time? Does the new version enable me to define my own scopes? For example, what if I want a "conversation" scope like Seam supposedly supports?
Let's not get into the MVC or AOP frameworks. [Un]fortunately I'm not using a dependency injection container at all at the moment. Don't think PicoContainer is getting off easily. It has most of the same problems, but I think Aslak and Jon have moved on to Ruby pastures. Are there any other frameworks that don't have these same problems?
Fortunately, simply adopting dependency injection design patterns gets you 90% of the way, further if you don't need encouragement to do the right thing. That's the approach I recommend. I certainly don't see myself adopting Spring anytime soon. I'm better off without it. If you do, go in with your eyes wide open. Be skeptical, critical. Just because someone has a popular Open Source framework, they have slick marketing, and they're supported by a big vendor (IBM pushed Struts on me for a number of years after all), it doesn't necessarily mean they know what's best for you or even that they know better than you.
Update: A coworker sent me a link to a Chinese translation of this entry.