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.
Best Solution
TL;DR
The
@Autowired
annotation spares you the need to do the wiring by yourself in the XML file (or any other way) and just finds for you what needs to be injected where and does that for you.Full explanation
The
@Autowired
annotation allows you to skip configurations elsewhere of what to inject and just does it for you. Assuming your package iscom.mycompany.movies
you have to put this tag in your XML (application context file):This tag will do an auto-scanning. Assuming each class that has to become a bean is annotated with a correct annotation like
@Component
(for simple bean) or@Controller
(for a servlet control) or@Repository
(forDAO
classes) and these classes are somewhere under the packagecom.mycompany.movies
, Spring will find all of these and create a bean for each one. This is done in 2 scans of the classes - the first time it just searches for classes that need to become a bean and maps the injections it needs to be doing, and on the second scan it injects the beans. Of course, you can define your beans in the more traditional XML file or with an@Configuration
class (or any combination of the three).The
@Autowired
annotation tells Spring where an injection needs to occur. If you put it on a methodsetMovieFinder
it understands (by the prefixset
+ the@Autowired
annotation) that a bean needs to be injected. In the second scan, Spring searches for a bean of typeMovieFinder
, and if it finds such bean, it injects it to this method. If it finds two such beans you will get anException
. To avoid theException
, you can use the@Qualifier
annotation and tell it which of the two beans to inject in the following manner:Or if you prefer to declare the beans in your XML, it would look something like this:
In the
@Autowired
declaration, you need to also add the@Qualifier
to tell which of the two color beans to inject:If you don't want to use two annotations (the
@Autowired
and@Qualifier
) you can use@Resource
to combine these two:The
@Resource
(you can read some extra data about it in the first comment on this answer) spares you the use of two annotations and instead, you only use one.I'll just add two more comments:
@Inject
instead of@Autowired
because it is not Spring-specific and is part of theJSR-330
standard.@Inject
/@Autowired
on a constructor instead of a method. If you put it on a constructor, you can validate that the injected beans are not null and fail fast when you try to start the application and avoid aNullPointerException
when you need to actually use the bean.Update: To complete the picture, I created a new question about the
@Configuration
class.