annotation-config和component-scan的區別
-
< context:annotation-config > 是用於激活那些已經在spring容器裏註冊過的bean
(無論是通過xml的方式還是通過package sanning的方式)上面的註解
-
< context:component-scan >除了具有< context:annotation-config >的功能之外,
< context:component-scan >還可以在指定的package下掃描以及註冊javabean
有三個class A,B,C,並且B,C的對象被注入到A中
package com.zr.pojo;
public class B {
public B() {
System.out.println("creating bean B: " + this);
}
}
package com.zr.pojo;
public class C {
public C() {
System.out.println("creating bean C: " + this);
}
}
package com.zr.pojo1;
import com.zr.pojo.B;
import com.zr.pojo.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中加入下面的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bBean" class="com.zr.pojo.B"/>
<bean id="cBean" class="com.zr.pojo.C"/>
<bean id="aBean" class="com.zr.pojo1.A">
<property name="bbb" ref="bBean"/>
<property name="ccc" ref="cBean"/>
</bean>
</beans>
加載applicationContext.xml配置文件,將得到下面的結果:
creating bean B: com.zr.pojo.B@6483f5ae
creating bean C: com.zr.pojo.C@282003e1
creating bean A: com.zr.pojo1.A@7fad8c79
setting A.bbb with com.zr.pojo.B@6483f5ae
setting A.ccc with com.zr.pojo.C@282003e1
完全通過xml的方式,太過時了
下面通過註解的方式來簡化我們的xml配置文件
首先,我們使用@Autowired的方式將對象bbb和ccc注入到A中
package com.zr.pojo1;
import com.zr.pojo.B;
import com.zr.pojo.C;
import org.springframework.beans.factory.annotation.Autowired;
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 >
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bBean" class="com.zr.pojo.B"/>
<bean id="cBean" class="com.zr.pojo.C"/>
<bean id="aBean" class="com.zr.pojo1.A"/>
</beans>
加載applicationContext.xml配置文件之後,得到下面的結果
creating bean B: com.zr.pojo.B@768b970c
creating bean C: com.zr.pojo.C@290dbf45
creating bean A: com.zr.pojo1.A@12028586
ClassA中顯然沒有注入屬性,結果是錯誤的的,究竟是因爲什麼呢?爲什麼屬性沒有被注入進去呢?
是因爲註解本身並不能夠做任何事情,它們只是最基本的組成部分
我們需要能夠處理這些註解的處理工具來處理這些註解
這就是< context:annotation-config > 所做的事情,用於激活那些已經在spring容器裏註冊過的bean的註解
將applicationContext.xml配置文件作如下修改
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean id="bBean" class="com.zr.pojo.B"/>
<bean id="cBean" class="com.zr.pojo.C"/>
<bean id="aBean" class="com.zr.pojo1.A"/>
</beans>
加載applicationContext.xml配置文件之後,將得到下面的結果:
creating bean B: com.zr.pojo.B@36c88a32
creating bean C: com.zr.pojo.C@1d119efb
creating bean A: com.zr.pojo1.A@35047d03
setting A.ccc with com.zr.pojo.C@1d119efb
setting A.bbb with com.zr.pojo.B@36c88a32
結果正確了
但是如果將代碼作如下修改
package com.zr.pojo;
import org.springframework.stereotype.Component;
@Component
public class B {
public B() {
System.out.println("creating bean B: " + this);
}
}
package com.zr.pojo;
import org.springframework.stereotype.Component;
@Component
public class C {
public C() {
System.out.println("creating bean C: " + this);
}
}
package com.zr.pojo1;
import com.zr.pojo.B;
import com.zr.pojo.C;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@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配置文件修改爲:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
當加載applicationContext.xml配置文件之後,卻沒有任何輸出,這是爲什麼呢?
因爲<context:annotation-config />僅能夠在已經在已經註冊過的bean上面起作用
對於沒有在spring容器中註冊的bean,它並不能執行任何操作
但是不用擔心,< context:component-scan >除了具有<context:annotation-config />的功能之外,還具有自動將帶有@component,@service,@Repository等註解的對象註冊到spring容器中的功能
我們將applicationContext.xml配置文件作如下修改:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.zr.pojo"/>
<context:component-scan base-package="com.zr.pojo1"/>
</beans>
加載applicationContext.xml就會得到下面的結果:
creating bean B: com.zr.pojo.B@6b81ce95
creating bean C: com.zr.pojo.C@16293aa2
creating bean A: com.zr.pojo1.A@2d7275fc
setting A.bbb with com.zr.pojo.B@6b81ce95
setting A.ccc with com.zr.pojo.C@16293aa2
結果正確
回頭看下applicationContext.xml文件,已經簡化爲兩行context:component-scan了,是不是很簡單?
那如果在applicationContext.xml手動加上下面的配置,也就是說
既在applicationContext.xml中手動的註冊了A的實例對象,
同時,通過component-scan去掃描並註冊B,C的對象,如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.zr.pojo"/>
<bean id="aBean" class="com.zr.pojo1.A"/>
</beans>
結果正確:
creating bean B: com.zr.pojo.B@6b81ce95
creating bean C: com.zr.pojo.C@16293aa2
creating bean A: com.zr.pojo1.A@2d7275fc
setting A.ccc with com.zr.pojo.C@16293aa2
setting A.bbb with com.zr.pojo.B@6b81ce95
雖然class A並不是通過掃描的方式註冊到容器中的 ,
但是< context:component-scan > 所產生的的處理那些註解的處理器工具,會處理所有綁定到容器上面的bean,不管是通過xml手動註冊的還是通過scanning掃描註冊的。
那麼,如果我們通過下面的方式呢?我們既配置了<context:annotation-config />,又配置了<context:component-scan base-package=“com.xxx” />,它們都具有處理在容器中註冊的bean裏面的註解的功能。會不會出現重複注入的情況呢?
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<context:component-scan base-package="com.zr.pojo"/>
<bean id="aBean" class="com.zr.pojo1.A"/>
</beans>
結果如下,沒有出現:
creating bean B: com.zr.pojo.B@37afeb11
creating bean C: com.zr.pojo.C@2d7275fc
creating bean A: com.zr.pojo1.A@79e2c065
setting A.bbb with com.zr.pojo.B@37afeb11
setting A.ccc with com.zr.pojo.C@2d7275fc
因爲<context:annotation-config />和 < context:component-scan >同時存在的時候,前者會被忽略
也就是那些@autowire,@resource等注入註解只會被注入一次
哪怕是你手動的註冊了多個處理器,spring仍然只會處理一次:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<context:component-scan base-package="com.zr.pojo"/>
<bean id="aBean" class="com.zr.pojo1.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" />
</beans>
結果仍是正確的:
creating bean B: com.zr.pojo.B@515aebb0
creating bean C: com.zr.pojo.C@399f45b1
creating bean A: com.zr.pojo1.A@3a93b025
setting A.ccc with com.zr.pojo.C@399f45b1
setting A.bbb with com.zr.pojo.B@515aebb0