Spring <context:annotation-config> 和 <context:component-scan>区别
2017-07-11 20:19
387 查看
原版:
https://stackoverflow.com/questions/7414794/difference-between-contextannotation-config-vs-contextcomponent-scan/
翻译版:
http://www.cnblogs.com/leiOOlei/p/3713989.html
I'll use some examples to show the differences/similarities.
Lets start with a basic setup of three beans of type
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 lets use those to simplify the XML.
First, lets autowire the
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.
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
But that won't be a problem for
When I load the context I get the following output:
Hmmmm... something is missing. Why?
If you look closelly at the classes, class
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
We still get the correct result:
Even if the bean for class
But what if we have the following XML, will we get duplicated beans because we've specified both
No, no duplications, We again get the expected result:
That's because both tags register the same processing tools (
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 raps it up.
I hope this information along with the responses from @Tomasz Nurkiewicz and @Sean Patrick Floyd are all you need to understand how
https://stackoverflow.com/questions/7414794/difference-between-contextannotation-config-vs-contextcomponent-scan/
翻译版:
http://www.cnblogs.com/leiOOlei/p/3713989.html
<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.
Lets start with a basic setup of three beans of type
A,
Band
C, with
Band
Cbeing injected into
A.
package com.xxx; public class B { public B() { System.out.println("creating bean B: " + this); } } package com.xxx; public class C { public C() { System.out.println("creating bean C: " + this); } } package com.yyy; import com.xxx.B; import com.xxx.C; public class A { private B bbb; private C ccc; public A() { System.out.println("creating bean A: " + this); } public void setBbb(B bbb) { System.out.println("setting A.bbb with " + bbb); this.bbb = bbb; } public void setCcc(C ccc) { System.out.println("setting A.ccc with " + ccc); this.ccc = ccc; } }
With the following XML configuration :
<bean id="bBean" class="com.xxx.B" /> <bean id="cBean" class="com.xxx.C" /> <bean id="aBean" class="com.yyy.A"> <property name="bbb" ref="bBean" /> <property name="ccc" ref="cBean" /> </bean>
Loading the context produces the following output:
creating bean B: com.xxx.B@c2ff5 creating bean C: com.xxx.C@1e8a1f6 creating bean A: com.yyy.A@1e152c5 setting A.bbb with com.xxx.B@c2ff5 setting A.ccc with com.xxx.C@1e8a1f6
OK, this is the expected output. But this is "old style" Spring. Now we have annotations so lets use those to simplify the XML.
First, lets autowire the
bbband
cccproperties on bean
Alike so:
package com.yyy; import org.springframework.beans.factory.annotation.Autowired; import com.xxx.B; import com.xxx.C; public class A { private B bbb; private C ccc; public A() { System.out.println("creating bean A: " + this); } @Autowired public void setBbb(B bbb) { System.out.println("setting A.bbb with " + bbb); this.bbb = bbb; } @Autowired public void setCcc(C ccc) { System.out.println("setting A.ccc with " + ccc); this.ccc = ccc; } }
This allows me to remove the following rows from the XML:
<property name="bbb" ref="bBean" /> <property name="ccc" ref="cBean" />
My XML is now simplified to this:
<bean id="bBean" class="com.xxx.B" /> <bean id="cBean" class="com.xxx.C" /> <bean id="aBean" class="com.yyy.A" />
When I load the context I get the following output:
creating bean B: com.xxx.B@5e5a50 creating bean C: com.xxx.C@54a328 creating bean A: com.yyy.A@a3d4cf
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:
<context:annotation-config />
<bean id="bBean" class="com.xxx.B" /> <bean id="cBean" class="com.xxx.C" /> <bean id="aBean" class="com.yyy.A" />
when I load the application context I get the proper result:
creating bean B: com.xxx.B@15663a2 creating bean C: com.xxx.C@cd5f8b creating bean A: com.yyy.A@157aa53 setting A.bbb with com.xxx.B@15663a2 setting A.ccc with com.xxx.C@cd5f8b
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:
package com.xxx; import org.springframework.stereotype.Component; @Component public class B { public B() { System.out.println("creating bean B: " + this); } } package com.xxx; import org.springframework.stereotype.Component; @Component public class C { public C() { System.out.println("creating bean C: " + this); } } package com.yyy; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.xxx.B; import com.xxx.C; @Component public class A { private B bbb; private C ccc; public A() { System.out.println("creating bean A: " + this); } @Autowired public void setBbb(B bbb) { System.out.println("setting A.bbb with " + bbb); this.bbb = bbb; } @Autowired public void setCcc(C ccc) { System.out.println("setting A.ccc with " + ccc); this.ccc = ccc; } }
While in the XML we only keep this:
<context:annotation-config />
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:
<context:component-scan base-package="com.xxx" />
When I load the context I get the following output:
creating bean B: com.xxx.B@1be0f0a creating bean C: com.xxx.C@80d1ff
Hmmmm... something is missing. Why?
If you look closelly at the classes, class
Ahas package
com.yyybut I've specified in the
<context:component-scan>to use package
com.xxxso this completely missed my
Aclass and only picked up
Band
Cwhich are on the
com.xxxpackage.
To fix this, I add this other package also:
<context:component-scan base-package="com.xxx,com.yyy" />
and now we get the expected result:
creating bean B: com.xxx.B@cd5f8b creating bean C: com.xxx.C@15ac3c9 creating bean A: com.yyy.A@ec4a87 setting A.bbb with com.xxx.B@cd5f8b setting A.ccc with com.xxx.C@15ac3c9
And that's it! Now you don't have XML definitions anymore, you have annotations.
As a final example, keeping the annotated classes
A,
Band
Cand adding the following to the XML, what will we get after loading the context?
<context:component-scan base-package="com.xxx" /> <bean id="aBean" class="com.yyy.A" />
We still get the correct result:
creating bean B: com.xxx.B@157aa53 creating bean C: com.xxx.C@ec4a87 creating bean A: com.yyy.A@1d64c37 setting A.bbb with com.xxx.B@157aa53 setting A.ccc with com.xxx.C@ec4a87
Even if the bean for class
Aisn't obtained by scanning, the processing tools are still applied by
<context:component-scan>on all beans registered in the application context, even for
Awhich 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>?
<context:annotation-config />
<context:component-scan base-package="com.xxx" /> <bean id="aBean" class="com.yyy.A" />
No, no duplications, We again get the expected result:
creating bean B: com.xxx.B@157aa53 creating bean C: com.xxx.C@ec4a87 creating bean A: com.yyy.A@1d64c37 setting A.bbb with com.xxx.B@157aa53 setting A.ccc with com.xxx.C@ec4a87
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:
<context:annotation-config />
<context:component-scan base-package="com.xxx" /> <bean id="aBean" class="com.yyy.A" />
<bean id="bla" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla1" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla2" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla3" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
will still generate the following result:
creating bean B: com.xxx.B@157aa53 creating bean C: com.xxx.C@ec4a87 creating bean A: com.yyy.A@25d2b2 setting A.bbb with com.xxx.B@157aa53 setting A.ccc with com.xxx.C@ec4a87
OK, that about raps 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.
相关文章推荐
- Spring <context:annotation-config> 和 <context:component-scan>区别
- Spring 开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别
- Spring 开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别
- Spring 开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别
- <context:annotation-config> 和 <context:component-scan>的区别
- Spring 开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别
- spring <context:annotation-config> 跟 <context:component-scan>诠释及区别
- spring中<context:annotation-config> 跟 <context:component-scan>的区别
- spring <context:annotation-config> 跟 <context:component-scan>诠释及区别
- <context:annotation-config> vs <context:component-scan> 的区别
- Spring 开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别
- Spring 开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别
- spring <context:annotation-config> 跟 <context:component-scan>诠释及区别
- <context:annotation-config> 和 <context:component-scan>的区别
- Spring 开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别
- Spring 开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别
- Spring <context:annotation-config> 和 <context:component-scan>区别
- spring配置中<context:annotation-config> 和 <context:component-scan>区别
- Spring 开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别
- <context:annotation-config> 和 <context:component-scan>的区别