一、簡介
? Spring容器負責創建應用程序中的bean并通過DI來協調這些對象之間的關系。Spring具有非常大的靈活性,它提供了三種主要的裝配機制:
- 在XML中進行顯示配置;
- 在Java中進行顯示配置;
- 隱式的bean發現機制和自動裝配。
二、在XML中進行顯示配置
1. 聲明一個簡單的bean
1. 創建CD接口
public interface CompactDisc {void play();
}
2. 創建NowAndThen類
public class NowAndThen implements CompactDisc{private String title = "Now And Then.";private String artist = "The Beatles";@Overridepublic void play() {System.out.println("Playing " + title + " by " + artist);}}
3. 在bean.xml文件中配置
<!-- 通過class屬性來聲明一個簡單的bean,此時因為沒有指定ID,bean的ID將會是com.shiftycat.soundsystem.NowAndThen#0 -->
<bean class="com.shiftycat.soundsystem.NowAndThen"/>
<!-- 使用id屬性可以用來指定ID -->
<bean id="CompactDisc" class="com.shiftycat.soundsystem.NowAndThen"/>
4. 進行測試
@Test
public void compactDiscTest() {ClassPathXmlApplicationContext classPathXmlApplicationContext =new ClassPathXmlApplicationContext("bean.xml");CompactDisc compactDisc = classPathXmlApplicationContext.getBean(CompactDisc.class);compactDisc.play();
}
5. 測試結果
Playing Now And Then. by The Beatles
2. 借助構造器注入初始化bean
? 構造器注入有兩種方案:
constructor-arg
元素- 使用Spring 3.0所引入的c-命名空間
1. 創建CD接口
public interface CompactDisc {void play();
}
2. 創建NowAndThen類
public class NowAndThen implements CompactDisc{private String title = "Now And Then.";private String artist = "The Beatles";@Overridepublic void play() {System.out.println("Playing " + title + " by " + artist);}}
3. 創建MediaPlayer接口
public interface MediaPlayer {void play();
}
4. 創建CDPlayer類
public class CDPlayer implements MediaPlayer{private CompactDisc cd;// 構造器注入public CDPlayer(CompactDisc cd) {this.cd = cd;}@Overridepublic void play() {System.out.println("Loading...");cd.play();}
}
5. 在bean.xml文件中配置
<bean id="CompactDisc" class="com.shiftycat.soundsystem.NowAndThen"/>\
<!-- 第一種配置方案:`constructor-arg`元素 -->
<bean id="cdPlayer" class="com.shiftycat.soundsystem.CDPlayer"><constructor-arg ref="CompactDisc"/>
</bean>
<!-- 第二種配置方案:使用Spring 3.0所引入的c-命名空間 -->
<!-- c:構造器參數名-ref=“要注入的bean的ID” -->
<bean id="cdPlayer" class="com.shiftycat.soundsystem.CDPlayer" c:cd-ref="CompactDisc"/>
<!-- 或者將參數的名稱替換為"_0"或者"_" -->
<bean id="cdPlayer" class="com.shiftycat.soundsystem.CDPlayer" c:_0-ref="CompactDisc" />
<bean id="cdPlayer" class="com.shiftycat.soundsystem.CDPlayer" c:_-ref="CompactDisc" />
6. 進行測試
@Test
public void cdPlayerTest() {ClassPathXmlApplicationContext classPathXmlApplicationContext =new ClassPathXmlApplicationContext("bean.xml");CDPlayer cdPlayer = classPathXmlApplicationContext.getBean(CDPlayer.class);cdPlayer.play();}
7. 測試結果
Loading...
Playing Now And Then. by The Beatles
將字面量注入到構造器中
1. 創建BlackDisc類
public class BlackDisc implements CompactDisc{private String title;private String artist;public BlackDisc(String title, String artist) {this.title = title;this.artist = artist;}@Overridepublic void play() {System.out.println("Playing " + title + " by " + artist);}
}
2. 在bean.xml中進行配置
<bean id="blackDisc" class="com.shiftycat.soundsystem.BlackDisc"><constructor-arg value="Now And Then." /><constructor-arg value="The Beatles" />
</bean><bean id="blackDisc" class="com.shiftycat.soundsystem.BlackDisc"c:title="Now And Then."c:artist="The Beatles"
/><bean id="blackDisc" class="com.shiftycat.soundsystem.BlackDisc"c:_0="Now And Then."c:_1="The Beatles"
/>
3. 進行測試
@Test
public void blackDiscTest() {ClassPathXmlApplicationContext classPathXmlApplicationContext =new ClassPathXmlApplicationContext("bean.xml");BlackDisc blackDisc = classPathXmlApplicationContext.getBean(BlackDisc.class);blackDisc.play();
}
4. 測試結果
Playing Now And Then. by The Beatles
P.S. 裝配集合
public class BlackDisc implements CompactDisc {private String title;private String artist;private List<String> tracks;public BlackDisc(String title, String artist, List<String> tracks) {this.title = title;this.artist = artist;this.tracks = tracks;}@Overridepublic void play() {System.out.println("Playing " + title + " by " + artist);for (String track : tracks) {System.out.println("-Track: " + track);}}
}
<bean id="blackDisc" class="com.shiftycat.soundsystem.BlackDisc"><constructor-arg value="Now And Then." /><constructor-arg value="The Beatles" /><constructor-arg><list><value>I know it's true</value><value>It's all because of you</value><value>And if I make it through</value><value>It's all because of you</value><value>And now and then</value></list></constructor-arg>
</bean>
Playing Now And Then. by The Beatles
-Track: I know it's true
-Track: It's all because of you
-Track: And if I make it through
-Track: It's all because of you
-Track: And now and then
3. 設置屬性初始化bean
一般而言,對于強依賴使用構造器注入,對可選性的依賴使用屬性注入。
1. 在CDPlayer類中設置setter方法
public class CDPlayer implements MediaPlayer{private CompactDisc cd;public void setCompactDisc(CompactDisc cd) {this.cd = cd;}@Overridepublic void play() {System.out.println("Loading...");cd.play();}
}
2. 在bean.xml文件中進行配置
<!-- 可以使用property進行配置-->
<bean id="cdPlayer" class="com.shiftycat.soundsystem.CDPlayer"><property name="compactDisc" ref="compactDisc"/>
</bean>
<!-- 或者使用p-命名空間性配置-->
<bean id="cdPlayer" class="com.shiftycat.soundsystem.CDPlayer"p:compactDisc-ref="compactDisc"/>
3. 進行測試
@Test
public void cdPlayerTest() {ClassPathXmlApplicationContext classPathXmlApplicationContext =new ClassPathXmlApplicationContext("bean.xml");CDPlayer cdPlayer = classPathXmlApplicationContext.getBean(CDPlayer.class);cdPlayer.play();
}
4. 測試結果
Loading...
Playing Now And Then. by The Beatles
將字面量注入到屬性中
1. 在WhiteDisc類中設置setter方法
public class WhiteDisc implements CompactDisc{private String title;private String artist;private List<String> tracks;public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getArtist() {return artist;}public void setArtist(String artist) {this.artist = artist;}public List<String> getTracks() {return tracks;}public void setTracks(List<String> tracks) {this.tracks = tracks;}@Overridepublic void play() {System.out.println("Playing " + title + " by " + artist);for (String track : tracks) {System.out.println("-Track: " + track);}}
}
2. 在bean.xml文件中進行配置
<bean id="whileDisc" class="com.shiftycat.soundsystem.WhiteDisc"><property name="artist" value="Now And Then."/><property name="title" value="The Beatles" /><property name="tracks"><list><value>I know it's true</value><value>It's all because of you</value><value>And if I make it through</value><value>It's all because of you</value><value>And now and then</value></list></property>
</bean>
<!--或者-->
<bean id="whileDisc" class="com.shiftycat.soundsystem.WhiteDisc"p:artist="Now And Then."p:title="The Beatles"><property name="tracks"><list><value>I know it's true</value><value>It's all because of you</value><value>And if I make it through</value><value>It's all because of you</value><value>And now and then</value></list></property>
</bean>
<!--或者-->
<bean id="whileDisc" class="com.shiftycat.soundsystem.WhiteDisc"p:artist="Now And Then."p:title="The Beatles"p:tracks-ref="tracks"
>
</bean><util:list id="tracks"><value>I know it's true</value><value>It's all because of you</value><value>And if I make it through</value><value>It's all because of you</value><value>And now and then</value>
</util:list>
3. 進行測試
@Test
public void whiteDiscTest() {ClassPathXmlApplicationContext classPathXmlApplicationContext =new ClassPathXmlApplicationContext("bean.xml");WhiteDisc whiteDisc = classPathXmlApplicationContext.getBean(WhiteDisc.class);whiteDisc.play();
}
4. 測試結果
Playing The Beatles by Now And Then.
-Track: I know it's true
-Track: It's all because of you
-Track: And if I make it through
-Track: It's all because of you
-Track: And now and then
三、在Java中進行顯式配置
1. 聲明簡單的bean
1. 創建配置類
@Configuration
public class CDPlayerConfig {}
2. 聲明簡單的bean
@Configuration
public class CDPlayerConfig {@Beanpublic CompactDisc nowAndThen() {return new nowAndThen();}}
2. 借助JavaConfig實現注入
@Configuration
//@ComponentScan(basePackages = "com.shiftycat.soundsystem") //在Spring中啟動組件掃描,默認掃描該類所在包及這個包下的所有子包
public class CDPlayerConfig {@Beanpublic CompactDisc nowAndThen() {return new nowAndThen();}// 方法一: 最簡單的方法是引用創建bean的方法@Beanpublic CDPlayer cdPlayer() {return new CDPlayer(nowAndThen());}// 方法二: 請求一個CompactDisc作為參數,將CompactDisc注入到CDPlayer的構造器中,// 而且不用明確引用CompactDisc的@Bean方法。@Beanpublic CDPlayer cdPlayer(CompactDisc compactDisc) {return new CDPlayer(compactDisc);}// 方法三: 通過setter方法注入CompactDisc@Beanpublic CDPlayer cdPlayer(CompactDisc compactDisc) {CDPlayer cdPlayer = new CDPlayer();cdPlayer.setCd(compactDisc);return cdPlayer;}
}
四、隱式的bean發現機制和自動裝配
1. 自動化裝配bean
? Spring通過兩個方面實現自動化裝配:
- 組件掃描(component scanning):Spring會自動發現應用上下文所創建的bean。
- 自動裝配(autowiring):Spring自動滿足bean之間的依賴。
2. 步驟
1. 創建可被發現的bean
public interface CompactDisc {void play();
}public class nowAndThen implements CompactDisc{private String title = "Now And Then.";private String artist = "The Beatles";@Overridepublic void play() {System.out.println("Playing " + title + " by " + artist);}
}public interface MediaPlayer {void play();
}
2. 開啟組件掃描
@Configuration
@ComponentScan(basePackages = "com.shiftycat.soundsystem") //在Spring中啟動組件掃描,默認掃描該類所在包及這個包下的所有子包
public class CDPlayerConfig {}
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd><context:component-scan base-package="com.shiftycat.soundsystem" />
</beans>
@Autowired
private CompactDisc compactDisc;@Test
public void compactDiscTest() {compactDisc.play();
}
Playing Now And Then. by The Beatles
3. 通過為bean添加注解實現自動裝配
不管是構造器、Setter方法還是其他的方法,Spring都會嘗試滿足方法參數上所聲明的依賴。假如有且只有一個bean匹配以來需求的話,那么這個bean將會被裝配進來。
@Component
public class CDPlayer implements MediaPlayer{private CompactDisc cd;@Autowiredpublic CDPlayer(CompactDisc cd) {this.cd = cd;}@Autowiredpublic void setCd(CompactDisc cd) {this.cd = cd;}@Overridepublic void play() {System.out.println("Loading...");cd.play();}
}
@Autowired
private CDPlayer cdPlayer;
@Test
public void cdPlayerTest() {cdPlayer.play();
}
Loading...
Playing Now And Then. by The Beatles
五、導入和混合配置
1. 在JavaConfig中引用XML配置
? 假如現存由兩個config文件和一個XML文件,如何實現在一個JavaConfig文件中引用兩個config文件并且在其中引入XML配置文件。
1. 配置文件1
public interface CompactDisc {void play();
}@Component
public class NowAndThen implements CompactDisc {private String title = "Now And Then.";private String artist = "The Beatles";@Overridepublic void play() {System.out.println("Playing " + title + " by " + artist);}
}@Configuration
public class CDConfig {@Beanpublic CompactDisc compactDisc() {return new NowAndThen();}
}
2. 配置文件2
public interface MediaPlayer {void play();
}@Component
public class CDPlayer implements MediaPlayer {private CompactDisc cd;public CDPlayer(CompactDisc cd) {this.cd = cd;}@Overridepublic void play() {System.out.println("Loading...");cd.play();}
}@Configuration
//@Import(CDConfig.class)
public class CDPlayerConfig {@Beanpublic CDPlayer cdPlayer(CompactDisc compactDisc) {return new CDPlayer(compactDisc);}
}
3. 配置文件3
public class BlackDisc implements CompactDisc {private String title;private String artist;private List<String> tracks;public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getArtist() {return artist;}public void setArtist(String artist) {this.artist = artist;}public List<String> getTracks() {return tracks;}public void setTracks(List<String> tracks) {this.tracks = tracks;}@Overridepublic void play() {System.out.println("Playing " + title + " by " + artist);for (String track : tracks) {System.out.println("-Track: " + track);}}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:c="http://www.springframework.org/schema/c"xmlns:p="http://www.springframework.org/schema/p"xmlns:util="http://www.springframework.org/schema/util"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsd"><bean id="blackDisc" class="com.shiftycat.importAndBlend.BlackDisc"p:artist="Now And Then."p:title="The Beatles"p:tracks-ref="tracks"></bean><util:list id="tracks"><value>I know it's true</value><value>It's all because of you</value><value>And if I make it through</value><value>It's all because of you</value><value>And now and then</value></util:list></beans>
4. 主要的Config文件
@Configuration
@Import({CDConfig.class, CDPlayerConfig.class})
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig {}
5. 進行測試
@Test
public void JavaConfigTest() {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(SoundSystemConfig.class);context.refresh();System.out.println("BlackDisc: ");CompactDisc blackDisc = context.getBean(BlackDisc.class);blackDisc.play();System.out.println("\nnowAndThen: ");CompactDisc nowAndThen = context.getBean(NowAndThen.class);nowAndThen.play();System.out.println("\nCDPlayer: ");CDPlayer player = context.getBean(CDPlayer.class);player.play();
}
6. 測試結果
BlackDisc:
Playing The Beatles by Now And Then.
-Track: I know it's true
-Track: It's all because of you
-Track: And if I make it through
-Track: It's all because of you
-Track: And now and thennowAndThen:
Playing Now And Then. by The BeatlesCDPlayer:
Loading...
Playing Now And Then. by The Beatles
2. 在XML配置中引用JavaConfig
? 與在JavaConfig中引用XML配置一樣,我們可以使用更高層次的配置文件,這個文件不聲明任何的bean,只是負責將兩個或更多的配置組合起來。
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 用來導入JavaConfig類配置到Xml文件中 --><bean class="com.shiftycat.importAndBlend.CDConfig" /><!-- 用來導入xml文件配置 --><import resource="cd-config.xml"/></beans>
《Spring實戰(第4版)》