[转载]Difference between <context:annotation-config> vs <context:component-scan>

在国外看到详细的说明一篇,非常浅显透彻。转给国内的筒子们:-)

原文标题:

Spring中的<context:annotation-config>与<context:component-scan>到底有什么不同?

原文出处:http://stackoverflow.com/a/7456501

<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 AB and C, with B and C being injected into A.

 1 package com.xxx;
 2 public class B {
 3   public B() {
 4     System.out.println("creating bean B: " + this);
 5   }
 6 }
 7
 8 package com.xxx;
 9 public class C {
10   public C() {
11     System.out.println("creating bean C: " + this);
12   }
13 }
14
15 package com.yyy;
16 import com.xxx.B;
17 import com.xxx.C;
18 public class A {
19   private B bbb;
20   private C ccc;
21   public A() {
22     System.out.println("creating bean A: " + this);
23   }
24   public void setBbb(B bbb) {
25     System.out.println("setting A.bbb with " + bbb);
26     this.bbb = bbb;
27   }
28   public void setCcc(C ccc) {
29     System.out.println("setting A.ccc with " + ccc);
30     this.ccc = ccc;
31   }
32 }

With the following XML configuration :

1 <bean id="bBean" class="com.xxx.B" />
2 <bean id="cBean" class="com.xxx.C" />
3 <bean id="aBean" class="com.yyy.A">
4   <property name="bbb" ref="bBean" />
5   <property name="ccc" ref="cBean" />
6 </bean>

Loading the context produces the following output:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

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 bbb and ccc properties on bean A like so:

 1 package com.yyy;
 2 import org.springframework.beans.factory.annotation.Autowired;
 3 import com.xxx.B;
 4 import com.xxx.C;
 5 public class A {
 6   private B bbb;
 7   private C ccc;
 8   public A() {
 9     System.out.println("creating bean A: " + this);
10   }
11   @Autowired
12   public void setBbb(B bbb) {
13     System.out.println("setting A.bbb with " + bbb);
14     this.bbb = bbb;
15   }
16   @Autowired
17   public void setCcc(C ccc) {
18     System.out.println("setting A.ccc with " + ccc);
19     this.ccc = ccc;
20   }
21 }

This allows me to remove the following rows from the XML:

1 <property name="bbb" ref="bBean" />
2 <property name="ccc" ref="cBean" />

My XML is now simplified to this:

1 <bean id="bBean" class="com.xxx.B" />
2 <bean id="cBean" class="com.xxx.C" />
3 <bean id="aBean" class="com.yyy.A" />

When I load the context I get the following output:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]

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:

1 <context:annotation-config />
2 <bean id="bBean" class="com.xxx.B" />
3 <bean id="cBean" class="com.xxx.C" />
4 <bean id="aBean" class="com.yyy.A" />

when I load the application context I get the proper result:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

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:

 1 package com.xxx;
 2 import org.springframework.stereotype.Component;
 3 @Component
 4 public class B {
 5   public B() {
 6     System.out.println("creating bean B: " + this);
 7   }
 8 }
 9
10 package com.xxx;
11 import org.springframework.stereotype.Component;
12 @Component
13 public class C {
14   public C() {
15     System.out.println("creating bean C: " + this);
16   }
17 }
18
19 package com.yyy;
20 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.stereotype.Component;
22 import com.xxx.B;
23 import com.xxx.C;
24 @Component
25 public class A {
26   private B bbb;
27   private C ccc;
28   public A() {
29     System.out.println("creating bean A: " + this);
30   }
31   @Autowired
32   public void setBbb(B bbb) {
33     System.out.println("setting A.bbb with " + bbb);
34     this.bbb = bbb;
35   }
36   @Autowired
37   public void setCcc(C ccc) {
38     System.out.println("setting A.ccc with " + ccc);
39     this.ccc = ccc;
40   }
41 }

While in the XML we only keep this:

1 <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:

1 <context:component-scan base-package="com.xxx" />

When I load the context I get the following output:

creating bean B: [email protected]
creating bean C: [email protected]

Hmmmm... something is missing. Why?

If you look closelly at the classes, class A has package com.yyy but I‘ve specified in the <context:component-scan> to use package com.xxx so this completely missed my A class and only picked up B and C which are on the com.xxx package.

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: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

And that‘s it! Now you don‘t have XML definitions anymore, you have annotations.

As a final example, keeping the annotated classes AB and C and adding the following to the XML, what will we get after loading the context?

1 <context:component-scan base-package="com.xxx" />
2 <bean id="aBean" class="com.yyy.A" />

We still get the correct result:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

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 for A 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>?

1 <context:annotation-config />
2 <context:component-scan base-package="com.xxx" />
3 <bean id="aBean" class="com.yyy.A" />

No, no duplications, We again get the expected result:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

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:

1 <context:annotation-config />
2 <context:component-scan base-package="com.xxx" />
3 <bean id="aBean" class="com.yyy.A" />
4 <bean id="bla" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
5 <bean id="bla1" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
6 <bean id="bla2" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
7 <bean id="bla3" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

will still generate the following result:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

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.

时间: 2025-01-31 06:38:50

[转载]Difference between <context:annotation-config> vs <context:component-scan>的相关文章

Mingyang.net:org.springframework.context.annotation.ConflictingBeanDefinitionException

org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'configController' for bean class [net.mingyang.modules.system.ConfigController] conflicts with existing, non-compatible bean definition of same

[org.springframework.context.annotation.AnnotationConfigBeanDefinitionParser] are only available on

<2015-4-10 下午02时55分35秒 CST> <Info> <Security> <BEA-090905> <Disabling the CryptoJ JCE Provider self-integrity check for better startup performance. To enable this check, specify -Dweblogic.security.allowCryptoJDefaultJCEVerifica

Context namespace element &#39;annotation-config&#39; and its parser class [org.springframework.context.annotation.AnnotationConfigBeanDefinitionParser]

严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListenerorg.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class pa

Context namespace element &#39;component-scan&#39; and its parser class [org.springframework.context.annotation.ComponentScanBeanDefinitionParser] are only available on JDK 1.5 and higher

Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [applicationContext.xml]; nested exception is java.lang.IllegalStateException: Context

context、config

Tomcat启动时已经创建了context,并使用它读取了web.xml中的参数,后台可以从context里获取参数 后台获取参数代码: ServletContext context = getServletContext(); String size = context.getInitParameter("size"); web.xml中参数配置: <context-param> <param-name>size</param-name> <

Spring context:component-scan中使用context:include-filter和context:exclude-filter

XML: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/sche

Spring配置问题——元素 &quot;context:component-scan&quot; 的前缀 &quot;context&quot; 未绑定

今天配置完: <!-- 自动扫描与装配,包含子包 --> <context:component-scan base-package="cn.itcast.oa"></context:component-scan> 这句话之后,validating 我的spring配置文件就一直走不下去了.当时以为是myeclipse卡了,之后去掉了所有的validating. 后来写了个单元测试测试Spring配置的时候,发现报错: columnNumber:54;

context:annotation-config配置和context:component-scan配置

<context:annotation-config> 是用于激活那些已经在spring容器里注册过的bean(无论是通过xml的方式还是通过package sanning的方式)上面的注解,是一个注解处理工具. 他的作用是式地向 Spring 容器注册 AutowiredAnnotationBeanPostProcessor. CommonAnnotationBeanPostProcessor. PersistenceAnnotationBeanPostProcessor. Required

Preemption Context Switches 和 Synchronization Context Switches

Preemption Context Switches度量的是操作系统任务调度器将处理器中的一个正在运行的线程切换为另一个更高优先级的线程的次数,即发生抢占的次数. Synchronization context switches度量的是由于显式调用线程同步API而发生线程切换的次数,如给多线程共享的变量加锁,多线程共同去修改,有些线程要阻塞在lock,直至占用锁的线程释放lock,这个度量反映的是线程间竞争的程度. 下面的实验来自VTune,旨在探究Preemption Context Swi