I'm learning Spring 3 and I don't seem to grasp the functionality behind <context:annotation-config>
and <context:component-scan>
.
From what I've read they seem to handle different annotations (@Required
, @Autowired
etc vs @Component
, @Repository
, @Service
etc), but also from what I've read they register the same bean post processor classes.
To confuse me even more, there is an annotation-config
attribute on <context:component-scan>
.
Can someone shed some light on these tags? What's similar, what's different, is one superseded by the other, they complete each other, do I need one of them, both?
Best Answer
<context:annotation-config>
is used to activate annotations in beans already registered in the application context (no matter if they were defined with XML or by package scanning).<context:component-scan>
can also do what<context:annotation-config>
does but<context:component-scan>
also scans packages to find and register beans within the application context.I'll use some examples to show the differences/similarities.
Let's start with a basic setup of three beans of type
A
,B
andC
, withB
andC
being injected intoA
.With the following XML configuration :
Loading the context produces the following output:
OK, this is the expected output. But this is "old style" Spring. Now we have annotations so let's use those to simplify the XML.
First, lets autowire the
bbb
andccc
properties on beanA
like so:This allows me to remove the following rows from the XML:
My XML is now simplified to this:
When I load the context I get the following output:
OK, this is wrong! What happened? Why aren't my properties autowired?
Well, annotations are a nice feature but by themselves, they do nothing whatsoever. They just annotate stuff. You need a processing tool to find the annotations and do something with them.
<context:annotation-config>
to the rescue. This activates the actions for the annotations that it finds on the beans defined in the same application context where itself is defined.If I change my XML to this:
when I load the application context I get the proper result:
OK, this is nice, but I've removed two rows from the XML and added one. That's not a very big difference. The idea with annotations is that it's supposed to remove the XML.
So let's remove the XML definitions and replace them all with annotations:
While in the XML we only keep this:
We load the context and the result is... Nothing. No beans are created, no beans are autowired. Nothing!
That's because, as I said in the first paragraph, the
<context:annotation-config />
only works on beans registered within the application context. Because I removed the XML configuration for the three beans there is no bean created and<context:annotation-config />
has no "targets" to work on.But that won't be a problem for
<context:component-scan>
which can scan a package for "targets" to work on. Let's change the content of the XML config into the following entry:When I load the context I get the following output:
Hmmmm... something is missing. Why?
If you look closely at the classes, class
A
has packagecom.yyy
but I've specified in the<context:component-scan>
to use packagecom.xxx
so this completely missed myA
class and only picked upB
andC
which are on thecom.xxx
package.To fix this, I add this other package also:
and now we get the expected result:
And that's it! Now you don't have XML definitions anymore, you have annotations.
As a final example, keeping the annotated classes
A
,B
andC
and adding the following to the XML, what will we get after loading the context?We still get the correct result:
Even if the bean for class
A
isn't obtained by scanning, the processing tools are still applied by<context:component-scan>
on all beans registered in the application context, even forA
which was manually registered in the XML.But what if we have the following XML, will we get duplicated beans because we've specified both
<context:annotation-config />
and<context:component-scan>
?No, no duplications, We again get the expected result:
That's because both tags register the same processing tools (
<context:annotation-config />
can be omitted if<context:component-scan>
is specified) but Spring takes care of running them only once.Even if you register the processing tools yourself multiple times, Spring will still make sure they do their magic only once; this XML:
will still generate the following result:
OK, that about wraps it up.
I hope this information along with the responses from @Tomasz Nurkiewicz and @Sean Patrick Floyd are all you need to understand how
<context:annotation-config>
and<context:component-scan>
work.