IOC
聲明一個(gè)簡單的bean
第一個(gè)例子:
首先設(shè)置一個(gè)接口Perofrmance表示參賽者玫恳。
package com.moonlit.myspring;
public interface Performer {
void perform() throws PerformanceException;
}
創(chuàng)建一個(gè)Juggler(雜技師)類繼承Performer表示參賽者是雜技師速兔。
package com.moonlit.myspring;
public class Juggler implements Performer {
private int beanBags = 3;
public Juggler() {
}
public Juggler(int beanBags) {
this.beanBags = beanBags;
}
public void perform() throws PerformanceException {
System.out.println("JUGGLING " + beanBags + " BEANBAGS");
}
}
在spring-idol.xml配置文件中定義一個(gè)名為duke的bean簿寂,他對(duì)應(yīng)Juggler類(把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-3.0.xsd">
<bean id="duke" class="com.moonlit.myspring.Juggler" />
</beans>
測試代碼:
package com.moonlit.practice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.moonlit.myspring.PerformanceException;
import com.moonlit.myspring.Performer;
public class FirstBean {
public static void main(String[] args) throws PerformanceException {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-idol.xml");
Performer performer = (Performer) context.getBean("duke");
performer.perform();
}
}
運(yùn)行結(jié)果如下:
JUGGLING 3 BEANBAGS
理解:首先定義了一個(gè)接口Performer谬晕,然后寫了一個(gè)類Juggler繼承自Peformer,Juggler有一個(gè)私有成員變量beanBags,他的默認(rèn)值是3碘裕,然后Juggler實(shí)現(xiàn)了Performer的perform方法,方法的輸出帶有beanBags的數(shù)量攒钳。
然后在測試的程序中帮孔,通過ApplicationContext類型對(duì)象加載了spring-idol.xml文件的內(nèi)容,而在xml文件中定義了名為"duke"的bean不撑,然后剛好就用到了文兢。
然后bean返回的是一個(gè)Juggler,所以將
Performer performer = (Performer) context.getBean("duke");
改成
Juggler performer = (Juggler) context.getBean("duke");
也是可以的焕檬,但是在這里想看的效果是通過application context返回的是不是一個(gè)Juggler姆坚,因?yàn)橥ㄟ^輸出的結(jié)果就可以知道了,所以這里用(Performer)实愚,對(duì)中輸出的效果顯示bean對(duì)應(yīng)的Performer真的是一個(gè)Juggler兼呵,這就是通過xml定義一個(gè)bean并通過application context獲得這個(gè)bean對(duì)象的整個(gè)過程兔辅。
另外一種寫法
bean沒有定義id
<?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-3.0.xsd">
<bean class="com.moonlit.myspring.Juggler" />
</beans>
測試代碼:
package com.moonlit.practice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.moonlit.myspring.PerformanceException;
import com.moonlit.myspring.Performer;
public class FirstBean {
public static void main(String[] args) throws PerformanceException {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-idol.xml");
Performer performer = (Performer) context.getBean("com.moonlit.myspring.Juggler");
performer.perform();
}
}
運(yùn)行結(jié)果如下:
JUGGLING 3 BEANBAGS
構(gòu)造器注入
之前講到的名為"duke"的bean有一個(gè)私有成員變量beanBags代表這個(gè)雜技師bean的一次性能夠拋出的最多的數(shù)量,Juggler有一個(gè)構(gòu)造函數(shù)萍程,構(gòu)造函數(shù)的第一個(gè)參數(shù)(這里只有一個(gè)參數(shù))beanBags是一個(gè)整型的值幢妄,用于傳遞給Juggler的私有成員變量beanBags。
構(gòu)造器注入的方法是:在bean中添加一個(gè)constructor-arg(如果構(gòu)造函數(shù)的參數(shù)有兩個(gè)茫负,那就添加兩個(gè)constructor-arg)蕉鸳。
在spring-idol.xml中修改bean "duke"如下:
<bean id="duke" class="com.moonlit.myspring.Juggler" >
<constructor-arg name="beanBags" value="15" />
</bean>
再次運(yùn)行FirstBean程序,輸出如下:
JUGGLING 15 BEANBAGS
可以看到通過構(gòu)造器諸如已經(jīng)把duke的beanBags改為了15忍法。
構(gòu)造函數(shù)中的參數(shù)可能不是一個(gè)基礎(chǔ)類型的變量潮尝,而可能是一個(gè)變量,這個(gè)時(shí)候只要把constructor-arg的value改成ref即可饿序,ref對(duì)應(yīng)的值需要被聲明稱一個(gè)bean元素勉失。
使用一個(gè)會(huì)唱歌的雜技師PoeticJuggler類來演示,PoeticJuggler繼承自Juggler原探,它具有一個(gè)Poem類型的私有成員變量poem乱凿,代表他要朗誦的詩歌。
Poem類:
package com.moonlit.myspring;
public interface Poem
{
void recite();
}
定義一首名為Sonnet29的類用于表示名為一首sonnet29的詩:http://shakespeare-online.com/sonnets/29.html
Sonnet29實(shí)現(xiàn)了Poem接口咽弦。
package com.moonlit.myspring;
public class Sonnet29 implements Poem {
private static String[] LINES = {
"When, in disgrace with fortune and men's eyes,",
"I all alone beweep my outcast state,",
"And trouble deaf heaven with my bootless cries,",
"And look upon myself, and curse my fate,",
"Wishing me like to one more rich in hope,",
"Featur'd like him, like him with friends possess'd,",
"Desiring this man's art and that man's scope,",
"With what I most enjoy contented least;",
"Yet in these thoughts myself almost despising,",
"Haply I think on thee, and then my state,",
"Like to the lark at break of day arising",
"From sullen earth, sings hymns at heaven's gate;",
"For thy sweet love remember'd such wealth brings",
"That then I scorn to change my state with kings.",
};
public Sonnet29() {
}
public void recite() {
for (String line : LINES)
System.out.println(line);
}
}
有了Poem和他的一個(gè)實(shí)現(xiàn)類Sonnet29之后徒蟆,開始來寫PoeticJuggler,他繼承自Juggler并且有一個(gè)Poem類型私有成員變量poem型型。
package com.moonlit.myspring;
public class PoeticJuggler extends Juggler {
private Poem poem;
public PoeticJuggler(Poem poem) {
super();
this.poem = poem;
}
public PoeticJuggler(int beanBags, Poem poem) {
super(beanBags);
this.poem = poem;
}
public void perform() throws PerformanceException {
super.perform();
System.out.println("While reciting...");
poem.recite();
}
}
并且段审,需要在xml文件中聲明Sonnet29和PoeticJuggler類對(duì)應(yīng)的bean。
<bean id="sonnet29" class="com.moonlit.myspring.Sonnet29" />
<bean id="poeticDuke" class="com.moonlit.myspring.PoeticJuggler">
<constructor-arg value="16" />
<constructor-arg ref="sonnet29" />
</bean>
可以看到闹蒜,"poeticDuke"使用了兩個(gè)constructor-arg來聲明參數(shù)寺枉,第一個(gè)參數(shù)使用value,第二個(gè)參數(shù)使用ref绷落,Sonnet29類型的bean--"connet29"姥闪。
使用測試程序查看效果:
package com.moonlit.practice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.moonlit.myspring.PerformanceException;
import com.moonlit.myspring.Performer;
public class FirstBean {
public static void main(String[] args) throws PerformanceException {
ApplicationContext context = new ClassPathXmlApplicationContext(
"spring-idol.xml");
Performer performer = (Performer) context.getBean("duke");
performer.perform();
}
}
程序輸出如下:
JUGGLING 16 BEANBAGS
While reciting...
When, in disgrace with fortune and men's eyes,
I all alone beweep my outcast state,
And trouble deaf heaven with my bootless cries,
And look upon myself, and curse my fate,
Wishing me like to one more rich in hope,
Featur'd like him, like him with friends possess'd,
Desiring this man's art and that man's scope,
With what I most enjoy contented least;
Yet in these thoughts myself almost despising,
Haply I think on thee, and then my state,
Like to the lark at break of day arising
From sullen earth, sings hymns at heaven's gate;
For thy sweet love remember'd such wealth brings
That then I scorn to change my state with kings.
理解:可以通過構(gòu)造器注入來模擬構(gòu)造函數(shù)傳入的參數(shù),通過constructor-arg value="XX"傳遞一個(gè)基本類型的參數(shù)XX嘱函,通過constructor-arg ref="XX"傳遞一個(gè)bean甘畅。
注入各種bean屬性
這里通過一個(gè)MoonlightPoet類來演示了注入Bean屬性property的效果。
package com.moonlit.myspring;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Properties;
public class MoonlightPoet {
private String name;
private int age;
private Poem poem;
private List<String> list;
private Map<String, String> map;
public void perform() {
System.out.println("name : " + name);
System.out.println("age : " + age);
poem.recite();
for (String val : list)
System.out.println("in list : " + val);
for (Entry<String, String> entry : map.entrySet())
System.out.println("in map : " + entry.getKey() + " -- " + entry.getValue());
}
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"spring-idol.xml");
MoonlightPoet moonlightPoet = (MoonlightPoet) context.getBean("moonlightPoet");
moonlightPoet.perform();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Poem getPoem() {
return poem;
}
public void setPoem(Poem poem) {
this.poem = poem;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
}
該bean在xml文件中定義如下:
<bean id="moonlightPoet" class="com.moonlit.myspring.MoonlightPoet">
<property name="name" value="moonlit" />
<property name="age" value="22" />
<property name="poem" ref="sonnet29" />
<property name="list">
<list>
<value>hello</value>
<value>world</value>
<!-- if bean, use <ref bean="XX"> -->
</list>
</property>
<property name="map">
<map>
<entry key="key1" value="value1" />
<entry key="key2" value="value2" />
<entry key="key3" value="value3" />
</map>
</property>
</bean>
輸出結(jié)果:
name : moonlit
age : 22
When, in disgrace with fortune and men's eyes,
I all alone beweep my outcast state,
And trouble deaf heaven with my bootless cries,
And look upon myself, and curse my fate,
Wishing me like to one more rich in hope,
Featur'd like him, like him with friends possess'd,
Desiring this man's art and that man's scope,
With what I most enjoy contented least;
Yet in these thoughts myself almost despising,
Haply I think on thee, and then my state,
Like to the lark at break of day arising
From sullen earth, sings hymns at heaven's gate;
For thy sweet love remember'd such wealth brings
That then I scorn to change my state with kings.
in list : hello
in list : world
in map : key1 -- value1
in map : key2 -- value2
in map : key3 -- value3
理解:
注入簡單值:
<property name="XX" value="YY" />
其中XX是變量名往弓,YY是值。
引用其他Bean:
<property name="XX" ref="YY">
其中XX是變量名蓄氧,YY是引用的bean的id函似。
裝配List:
<property name="XX">
<value>YY</value>
或者
<ref bean="ZZ">
</property>
其中XX是變量名,YY是值喉童,ZZ是引用的bean撇寞。
裝配Map:
<map>
<entry key="XX" value="YY" />
或者
<entry key="XX" value-ref="YY" />
或者
<entry key-ref="XX" value="YY" />
或者
<entry key-ref="XX" value-ref="YY" />
</map>
因?yàn)閙ap的key和value可以對(duì)應(yīng)一個(gè)基礎(chǔ)類型的值,也可以對(duì)應(yīng)一個(gè)bean,所以key,value對(duì)應(yīng)值蔑担,key-ref,value-ref對(duì)應(yīng)bean牌废。
使用Spring的命名空間p裝配屬性
可以在beans中添加
xmlns:p="http://www.springframework.org/schema/p"
來使用p:作為<bean>元素所有屬性的前綴來裝配Bean的屬性。用法如下:
<bean id="kenny" class="XX"
p:song = "Jingle Bells"
p:instrument-ref = "saxphone" />
-ref后綴作為一個(gè)標(biāo)識(shí)來告知Spring應(yīng)該裝配一個(gè)引用而不是字面值啤握。
自動(dòng)裝配bean屬性
Spring提供了四種類型的自動(dòng)裝配策略:
byName – 把與Bean的屬性具有相同名字(或者ID)的其他Bean自動(dòng)裝配到Bean的對(duì)應(yīng)屬性中鸟缕。
byType – 把與Bean的屬性具有相同類型的其他Bean自動(dòng)裝配到Bean的對(duì)應(yīng)屬性中。
constructor – 把與Bean的構(gòu)造器入?yún)⒕哂邢嗤愋偷钠渌鸅ean自動(dòng)裝配到Bean的對(duì)應(yīng)屬性中排抬。
autodetect – 首先使用costructor進(jìn)行自動(dòng)裝配懂从。如果失敗,再嘗試使用byType進(jìn)行自動(dòng)裝配蹲蒲。
這里以關(guān)羽和青龍偃月刀為例: 首先定義一個(gè)武器接口Weapon:
package com.moonlit.myspring;
public interface Weapon {
public void attack();
}
然后定義一個(gè)Weapon接口的實(shí)現(xiàn)Falchion類:
package com.moonlit.myspring;
public class Falchion implements Weapon {
public void attack() {
System.out.println("falcon is attacking!");
}
}
定義一個(gè)英雄接口Hero:
package com.moonlit.myspring;
public interface Hero {
public void perform();
}
然后定義一個(gè)Hero接口的實(shí)現(xiàn)Guanyu類(代表關(guān)羽):
package com.moonlit.myspring;
public class GuanYu implements Hero {
private Weapon weapon;
public void perform() {
System.out.println("GuanYu pick up his weapon.");
weapon.attack();
}
public Weapon getWeapon() {
return weapon;
}
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
}
在不涉及自動(dòng)裝配的情況下番甩,想要通過Spring的DI將Fachion類對(duì)象注入到Guanyu類的weapon屬性中,可以新建一個(gè)xml文件(這里取名為spring-idol.xml)并在里面填寫:
spring-idol.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-3.0.xsd">
<bean id="falchion" class="com.moonlit.myspring.Falchion" />
<bean id="guanyu" class="com.moonlit.myspring.GuanYu">
<property name="weapon" ref="falchion" />
</bean>
</beans>
其中最主要的內(nèi)容就是兩個(gè)bean的聲明部分:
<bean id="falchion" class="com.moonlit.myspring.Falchion" />
<bean id="guanyu" class="com.moonlit.myspring.GuanYu">
<property name="weapon" ref="falchion" />
</bean>
第一個(gè)bean標(biāo)簽定義了一個(gè)Falchion類型的bean届搁,第二個(gè)bean標(biāo)簽中將第一個(gè)bean作為weapon的值裝配到了weapon屬性中缘薛。 然后可以寫一個(gè)測試程序來查看效果:
package com.moonlit.practice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.moonlit.myspring.Hero;
public class AutowirePractice {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-idol.xml");
Hero guanyu = (Hero) context.getBean("guanyu");
guanyu.perform();
}
}
輸出結(jié)果如下:
GuanYu pick up his weapon.
falcon is attacking!
到目前為止還沒有涉及到自動(dòng)裝配的內(nèi)容,接下來開始講述自動(dòng)裝配的內(nèi)容卡睦。
byName自動(dòng)裝配
改變spring-idol.xml中bean聲明內(nèi)容的形式如下:
<bean id="weapon" class="com.moonlit.myspring.Falchion" />
<bean id="guanyu" class="com.moonlit.myspring.GuanYu" autowire="byName" />
得到一樣的結(jié)果宴胧。
將Falchion類的id去了一個(gè)和Guanyu類的屬性weapon一樣的名字,并且在guanyu bean中添加了autowire="byName"用于指明裝配類型是byName自動(dòng)裝配么翰。這個(gè)時(shí)候guanyu bean就是在上下文中找名為weapon的bean裝配到他自己的weapon屬性中牺汤。
byType自動(dòng)裝配
改變spring-idol.xml中bean聲明內(nèi)容的形式如下:
<bean id="falchion" class="com.moonlit.myspring.Falchion" />
<bean id="guanyu" class="com.moonlit.myspring.GuanYu" autowire="byType" />
得到一樣的結(jié)果。
這里已經(jīng)不用關(guān)注Falchion類對(duì)應(yīng)的bean的id是什么了浩嫌,因?yàn)橐呀?jīng)定義guanyu bean的autowire屬性為"byType"檐迟。這個(gè)時(shí)候guanyu bean會(huì)在上下文中尋找和weapon具有相同類型的類對(duì)應(yīng)的bean。
因?yàn)镚uanyu類的weapon實(shí)現(xiàn)Weapon借口码耐,整個(gè)上下文中目前只有一個(gè)Weapon接口的實(shí)現(xiàn)Falchion類追迟,所以以"byType"類型就檢測到了falchion bean并將其注入到了guanyu bean的weapon屬性中。
但是也會(huì)出現(xiàn)一種情況就是檢測的時(shí)候可能會(huì)出現(xiàn)多個(gè)相同type的bean骚腥,這個(gè)時(shí)候就不知道要裝配那個(gè)了敦间。比如,在新建一個(gè)實(shí)現(xiàn)Weapon接口的方天畫戟類HalBerd:
package com.moonlit.myspring;
public class Halberd implements Weapon {
public void attack() {
System.out.println("halberd is attacking!!!");
}
}
并且在xml文件中聲明一個(gè)新的halberd bean:
<bean id="halberd" class="com.moonlit.myspring.Halberd" />
在這種情況下就會(huì)出錯(cuò)束铭,因?yàn)橛袃蓚€(gè)bean滿足byType的結(jié)果廓块。
這個(gè)時(shí)候有兩種解決辦法:
第一種方法是將其中一個(gè)bean的primary屬性設(shè)為false,比如:將方天畫戟falchion bean的primary屬性設(shè)為true契沫,以防冠以使用方天畫戟(很好奇呂布死了之后带猴,赤兔馬歸關(guān)羽了,方天畫戟去哪里了):
<bean id="falchion" class="com.moonlit.myspring.Falchion" />
<bean id="halberd" class="com.moonlit.myspring.Halberd" primary="true" />
<bean id="guanyu" class="com.moonlit.myspring.GuanYu" autowire="byType" />
輸出結(jié)果如下:
GuanYu pick up his weapon.
halberd is attacking!!!
從輸出結(jié)果中可以看到懈万,關(guān)羽沒有使用青龍偃月刀拴清,而是使用方天畫戟進(jìn)行攻擊了靶病。
primary的默認(rèn)屬性是false。
第二種方法是設(shè)置其中一個(gè)bean的autowire-candidate屬性為false口予,比如:將方天畫戟的autowire-candidate屬性設(shè)為false:
<bean id="falchion" class="com.moonlit.myspring.Falchion" />
<bean id="halberd" class="com.moonlit.myspring.Halberd" primary="true" autowire-candidate="false" />
<bean id="guanyu" class="com.moonlit.myspring.GuanYu" autowire="byType" />
這個(gè)時(shí)候測試程序的輸出如下:
GuanYu pick up his weapon.
falcon is attacking!
可以看到這個(gè)時(shí)候關(guān)羽又重拾了青龍偃月刀娄周。可以看到沪停,當(dāng)halberd bean的autowire-candidate屬性設(shè)為false時(shí)煤辨,他將不會(huì)作為自動(dòng)裝配的競選bean之一,這個(gè)時(shí)候雖然halberd的primary屬性為true牙甫,但是halberd bean沒有參與自動(dòng)裝配的競選掷酗,所以自動(dòng)裝配到了falchion。
這種感覺就好像:“隔壁村李小花覬覦已久窟哺,但是一個(gè)要成為海賊王的男人泻轰,于是拒絕了她……最終她嫁給了隔壁老王,過上了幸福的生活”且轨。
使用注解裝配bean
使用@Autowired注解
從Spring2.5開始浮声,最有趣的一種裝配Spring Bean的方式是使用注解自動(dòng)裝配Bean的屬性。
Spring默認(rèn)禁用注解裝配旋奢,最簡單的啟用方式是使用Spring的context命名空間配置中的<context:annotation-config>元素泳挥,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<!-- bean declarations here -->
</beans>
繼續(xù)上一節(jié)的例子,在xml文件中定義兩個(gè)bean:falchion bean和guanyu bean至朗,為了實(shí)現(xiàn)@Autowired自動(dòng)裝配屉符,在GuanYu類中的setWeapon()方法前添加了@Autowired注解,如下:
GuanYu.java:
package com.moonlit.myspring;
import org.springframework.beans.factory.annotation.Autowired;
public class GuanYu implements Hero {
@Autowired
private Weapon weapon;
public void perform() {
System.out.println("Guan Yu pick up his weapon.");
weapon.attack();
}
public Weapon getWeapon() {
return weapon;
}
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
}
通過基于注解的方式锹引,可以不用在xml文件中為guanyu bean添加autowire屬性了矗钟。
spring-idol內(nèi)部的代碼:
<context:annotation-config />
<bean id="falchion" class="com.moonlit.myspring.Falchion" />
<bean id="guanyu" class="com.moonlit.myspring.GuanYu" />
@Autowired注解存在一個(gè)限制:
匹配多個(gè)Bean
限定歧義性的依賴
有可能存在多個(gè)bean滿足裝配條件,比如嫌变,這里吨艇,falchion bean和halberd bean都滿足裝配到guanyu bean的weapon屬性中的條件。此時(shí)如果只是用@Autowired注解的話就會(huì)出問題腾啥,才@Autowired注解下添加@Qualifier注解如下:
@Autowired
@Qualifier("falchion")
private Weapon weapon;
就會(huì)將falchion bean裝入到weapon中东涡。
如上所示,@Qualifier注解將嘗試注入ID為falchion的Bean倘待。
除了通過Bean的ID來限定疮跑,也可以給Bean添加一個(gè)qualifier屬性,通過這個(gè)qualifier屬性來獲得限定凸舵,如:
給halberd bean添加一個(gè)qualifier祸挪,值為"weaponOfGuanYu":
<bean id="halberd" class="com.moonlit.myspring.Halberd">
<qualifier value="weaponOfGuanYu" />
</bean>
然后對(duì)GuanYu類weapon類的注解如下:
@Autowired
@Qualifier("weaponOfGuanYu")
private Weapon weapon;
輸出如下:
Guan Yu pick up his weapon.
halberd is attacking!!!
可以看出,@qualifier降低了@Autowired的匹配范圍贞间,最終篩選得到了halberd bean裝入weapon屬性贿条。
這里的<qualifier>元素限定了方天畫戟(halberd)Bean是關(guān)羽使用的武器(weaponOgGuanYu)。除了可以在XML中指定qualifier增热,還可以使用Qualifier類來標(biāo)注Halberd類:
package com.moonlit.myspring;
import org.springframework.beans.factory.annotation.Qualifier;
@Qualifier("weaponOfGuanYu")
public class Halberd implements Weapon {
public void attack() {
System.out.println("halberd is attacking!!!");
}
}
程序運(yùn)行將得到相同的結(jié)果整以。
即使<context:annotation-config>有助于完全消除Spring配置文件中的元素,但是還是不能完全消除峻仇,仍然需要使用<bean>元素顯示定義Bean公黑。因此<context:component-scan>元素出現(xiàn)了,它除了完成<context:annotation-config>一樣的工作摄咆,還允許Spring自動(dòng)檢測Bean和定義Bean凡蚜。這就意味著不使用<bean>元素,Spring應(yīng)用中的大多數(shù)(或者所有)Bean都能夠自動(dòng)實(shí)現(xiàn)定義和裝配吭从。
自動(dòng)檢測
為了配置Spring自動(dòng)檢測朝蜘,需要使用<context:component-scan>元素來代替<context:annotation-config>元素:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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.moonlit.myspring">
</context:component-scan>
</beans>
<context:component-scan>元素會(huì)掃描指定的包以及所有子包,并查找出能夠自動(dòng)注冊(cè)為Spring Bean的類涩金。base-package屬性標(biāo)示了<context:component-scan>元素所掃描的包谱醇。
為自動(dòng)檢測標(biāo)注Bean
默認(rèn)情況下,<context:component-scan>查找使用構(gòu)造型(stereotype)注解所標(biāo)注的類步做,這些特殊的注解如下:
類型 說明
@component 通用的構(gòu)造型注解副渴,標(biāo)示該類為Spring 組件。
@Controller 標(biāo)識(shí)將該類定義為Spring MVC controller全度。
@Repository 標(biāo)識(shí)將該類定義為數(shù)據(jù)倉庫(例如:Dao層)煮剧。
@Service 標(biāo)識(shí)將該類定義為服務(wù)(例如:Service層)。
@component("guanyu")
ApplicationContext applicationContext
= new ClassPathXmlApplicationContext("spring.xml");
Hero hero = (Hero)applicationContext.getBean("guanyu");
hero.perform();