<context:annotation-config>,<context:component-scan>,<mvc:annotation-driven/>區(qū)別

<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)用程序上下文中掛起。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容