spring 註解的 跟 詮釋及區別

<context:annotation-config> 和 <context:component-scan>的區別java

Difference between <context:annotation-config> vs <context:component-scan>

 

<context:annotation-config> 是用於激活那些已經在spring容器裏註冊過的bean(不管是經過xml的方式仍是經過package sanning的方式)上面的註解,是一個註解處理工具。spring

<context:component-scan>除了具備<context:annotation-config>的功能以外,<context:component-scan>還能夠在指定的package下掃描以及註冊javabean 。app

 

下面咱們經過例子來詳細查看他們的區別,工具

有三個class   A,B,C,而且B,C的對象被注入到A中.this

 

[java] view plain copyspa

 print?.net

  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. }  

 

 

在applicationContext.xml中加入下面的配置 :3d

 

<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配置文件,將獲得下面的結果:code

 

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, 這個結果沒什麼好說的,就是徹底經過xml的方式,不過太過期了,下面經過註解的方式來簡化咱們的xml配置文件component

首先,咱們使用autowire的方式將對象bbb和ccc注入到A中:

 

 

[java] view plain copy

 print?

  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. }  

 

 

 

而後,咱們就能夠從applicationContext.xml中移除下面的配置

 

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

 

移除以後,咱們的applicationContext.xml配置文件就簡化爲下面的樣子了

 

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

 

當咱們加載applicationContext.xml配置文件以後,將獲得下面的結果:

 

creating bean B: com.xxx.B@5e5a50
creating bean C: com.xxx.C@54a328
creating bean A: com.yyy.A@a3d4cf

 

OK, 結果是錯誤的的,到底是由於什麼呢?爲何咱們的屬性沒有被注入進去呢?

是由於註解自己並不可以作任何事情,它們只是最基本的組成部分,咱們須要可以處理這些註解的處理工具來處理這些註解

這就是<context:annotation-config> 所作的事情

咱們將applicationContext.xml配置文件做以下修改:

 

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

 

當咱們加載applicationContext.xml配置文件以後,將獲得下面的結果:

 

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, 結果正確了。

 

下面演示<context:annotation-config> 跟 <context:component-scan>區別:

可是若是咱們將代碼做以下修改:

 

 

[java] view plain copy

 print?

  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. }  

 

 

 

 

applicationContext.xml配置文件修改成:

 

<context:annotation-config />

 

當咱們加載applicationContext.xml配置文件以後,卻沒有任何輸出,這是爲何呢?

那是由於<context:annotation-config />僅可以在已經在已經註冊過的bean上面起做用。

對於沒有在spring容器中註冊的bean,它並不能執行任何操做。

可是不用擔憂,<context:component-scan>除了具備<context:annotation-config />的功能以外,還具備自動將帶有@component,@service,@Repository等註解的對象註冊到spring容器中的功能。

咱們將applicationContext.xml配置文件做以下修改:

 

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

 

當咱們加載applicationContext.xml的時候,會獲得下面的結果:

 

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"/><context:component-scan base-package="com.xxx"/>
而後加載applicationContext.xml就會獲得下面的結果:
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文件,已經簡化爲:

 

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

 

了。

 

那若是咱們在applicationContext.xml手動加上下面的配置,也就是說既在applicationContext.xml中手動的註冊了A的實例對象,同時,經過component-scan去掃描並註冊B,C的對象

 

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

 

結果還是正確的:

 

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

 

雖然class  A並非經過掃描的方式註冊到容器中的 ,可是<context:component-scan> 所產生的的處理那些註解的處理器工具,會處理全部綁定到容器上面的bean,無論是經過xml手動註冊的仍是經過scanning掃描註冊的。

那麼,若是咱們經過下面的方式呢?咱們既配置了<context:annotation-config />,又配置了<context:component-scan base-package="com.xxx" />,它們都具備處理在容器中註冊的bean裏面的註解的功能。會不會出現重複注入的狀況呢?

 

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

 

不用擔憂,不會出現的:

 

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

 

由於<context:annotation-config />和 <context:component-scan>同時存在的時候,前者會被忽略。也就是那些@autowire,@resource等注入註解只會被注入一次

哪怕是你手動的註冊了多個處理器,spring仍然只會處理一次:

 

[xml] view plain copy

 print?

  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" />  

 

 

結果還是正確的:

 

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
相關文章
相關標籤/搜索