<context:annotation-config> 是用于激活那些已經(jīng)在spring容器里注冊過的bean(無論是通過xml的方式還是通過package sanning的方式)上面的注解,是一個注解處理工具。
<context:component-scan>除了具有<context:annotation-config>的功能之外,<context:component-scan>還可以在指定的package下掃描以及注冊javabean 。
先看一個完全通過XML配置的例子,之后將它改成注解形式。有三個classA,B,C,并且B,C的對象被注入到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;
}
}
//在applicationContext.xml中加入下面的配置 :
<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>
//加載applicationContext.xml配置文件,將得到下面的結(jié)果:
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
接下來使用Autowired的方式將對象bbb和ccc注入到A中:
使用<context:annotation-config />:
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;
}
}
然后,我們就可以從applicationContext.xml中移除下面的配置
<property name="bbb" ref="bBean"/>
<property name="ccc" ref="cBean"/>
移除之后,我們的applicationContext.xml配置文件就簡化為下面的樣子了。因為注解本身并不能夠做任何事情,它們只是最基本的組成部分,我們需要能夠處理這些注解的處理工具來處理這些注解,這就是<context:annotation-config> 所做的事情。
<context:annotation-config />
<bean id="bBean"class="com.xxx.B"/>
<bean id="cBean"class="com.xxx.C"/>
<bean id="aBean"class="com.yyy.A"/>
當(dāng)我們加載applicationContext.xml配置文件之后,將得到下面的結(jié)果:
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
如果不加<context:annotation-config />只會得到
creating bean B: com.xxx.B@15663a2
creating bean C: com.xxx.C@cd5f8b
creating bean A: com.yyy.A@157aa53
使用<context:component-scan>:
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;
}
}
applicationContext.xml配置文件修改為:
<context:annotation-config />
當(dāng)我們加載applicationContext.xml配置文件之后,卻沒有任何輸出,因為<context:annotation-config />僅能夠在已經(jīng)在已經(jīng)注冊過的bean上面起作用。對于沒有在spring容器中注冊的bean,它并不能執(zhí)行任何操作。這時就需要<context:component-scan>,<context:component-scan>除了具有<context:annotation-config />的功能之外,還具有自動將帶有@component,@service,@Repository等注解的對象注冊到spring容器中的功能。
我們將applicationContext.xml配置文件作如下修改:
<context:component-scan base-package="com.xxx"/>
當(dāng)我們加載applicationContext.xml的時候,會得到下面的結(jié)果:
creating bean B: com.xxx.B@1be0f0a
creating bean C: com.xxx.C@80d1ff
這是因為我們僅僅掃描了com.xxx包及其子包的類,而class A是在com.yyy包下,所以就掃描不到了
下面我們在applicationContext.xml中把com.yyy也加入進來:
<context:component-scan base-package="com.xxx,com.yyy"/>
然后加載applicationContext.xml就會得到下面的結(jié)果:
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
這時applicationContext.xml文件已經(jīng)簡化為:
<context:component-scan base-package="com.xxx,com.yyy"/>
<context:component-scan>所產(chǎn)生的的處理那些注解的處理器工具,會處理所有綁定到容器上面的bean,不管是通過xml手動注冊的還是通過scanning掃描注冊的。
如果我們同時配置了<context:annotation-config />和<context:component-scan base-package="com.xxx" />,它們都具有處理在容器中注冊的bean里面的注解的功能。會不會出現(xiàn)重復(fù)注入的情況呢?
在<context:annotation-config />和 <context:component-scan>同時存在的時候,前者會被忽略。也就是那些@autowire,@resource等注入注解只會被注入一次。
使用<mvc:annotation-driven/>:
不同于之前的兩個注解來自于Spring,<mvc:annotation-driven/>來自于Spring MVC,對應(yīng)的實現(xiàn)類是對應(yīng)的實現(xiàn)類是org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser。
<mvc:annotation-driven/>標簽可簡化springmvc的相關(guān)配置,默認情況下其會創(chuàng)建并注冊如下實例
1.RequestMappingHandlerMapping
2.BeanNameUrlHandlerMapping
3.RequestMappingHandlerAdapter
4.HttpRequestHandlerAdapter
5.SimpleControllerHandlerAdapter 等等。
沒有<mvc:annotation-driven />的@Controller只是一個普通的Bean。 它不會綁定到傳入的請求,它只是在應(yīng)用程序上下文中掛起。