Java – Spring @Autowired usage

autowiredjavaspring

What are the pros and cons of using @Autowired in a class that will be wired up by Spring?

Just to clarify, I'm talking specifically about the @Autowired annotation, not auto-wiring in XML.

I probably just don't understand it, but to me it almost seems like an anti-pattern – your classes start to become aware that they are tied to a DI framework, rather than just being POJOs. Maybe I'm a glutton for punishment, but I like having the external XML config for beans, and I like to have explicit wirings, so I know exactly what is wired where.

Best Answer

For a long time I believed that there was a value in having a "centralized, declarative, configuration" like the xml files we all used to use. Then I realized that most of the stuff in the files wasn't configuration - it was never changed anywhere after development, ever. Then I realized that "centralized" only has value in quite small systems - only in small systems will you ever be able to grok a configuration file as a whole. And what is really the value of understanding the wiring as a whole, when the same "wirings" are mostly duplicated by dependencies in the code? So the only thing I've kept is meta-data (annotations), which is still kind-of declarative. These never change at runtime and they're never "configuration" data that someone will change on the fly - so I think keeping it in the code is nice.

I use full auto-wiring as much as I can. I love it. I won't go back to old-style spring unless threatened at gun-point. My reasons for preferring fully @Autowired have changed over time.

Right now I think the most important reason for using autowiring is that there's one less abstraction in your system to keep track of. The "bean name" is effectively gone. It turns out the bean name only exists because of xml. So a full layer of abstract indirections (where you would wire bean-name "foo" into bean "bar") is gone. Now I wire the "Foo" interface into my bean directly, and implementation is chosen by run-time profile. This allows me to work with code when tracing dependencies and implementations. When I see an autowired dependency in my code I can just press the "go to implementation" key in my IDE and up comes the list of known implementations. In most cases there's just one implementation and I'm straight into the class. Can't be much simpler than that, and I always know exactly what implementation is being used (I claim that the opposite is closer to the truth with xml wiring - funny how your perspective changes!)

Now you could say that it's just a very simple layer, but each layer of abstraction that we add to our systems increase complexity. I really don't think the xml ever added any real value to any system I've worked with.

Most systems I've ever work with only have one configuration of the production runtime environment. There may be other configurations for test and so on.

I'd say that full autowiring is the ruby-on-rails of spring: It embraces the notion that there's a normal and common usage pattern that most use cases follow. With XML configuration you permit a lot of consistent/inconsistent configuration usage that may/may not be intended. I've seen so much xml configuration go overboard with inconsistencies - does it get refactored together with the code ? Thought not. Are those variations there for a reason? Usually not.

We hardly use qualifiers in our configuration, and found other ways to solve these situations. This is a clear "disadvantage" we encounter: We've slightly changed the way we code to make it interact smoother with autowiring: A customer repository no longer implements the generic Repository<Customer> interface but we make an interface CustomerRepository that extends Repository<Customer>. Sometimes there's also a trick or two when it comes to subclassing. But it usually just points us in the direction of stronger typing, which I find is almost always a better solution.

But yes, you're tying to a particular style of DI that mostly spring does. We don't even make public setters for dependencies any more (So you could argue that we're +1 in the encapsulation/information hiding department) We still have some xml in our system, but the xml basically only contains the anomalies. Full autowiring integrates nicely with xml.

The only thing we need now is for the @Component, @Autowired and the rest to be included in a JSR (like JSR-250), so we don't have to tie in with spring. This is the way things have been happening in the past (the java.util.concurrent stuff springs to mind), so I wouldn't be entirely surprised if this happened again.