經過將近五天的學習 坎坎坷坷地將第二章學完了 也算是走上了spring框架學習的正規 目前也僅僅懂一些為什么要用spring框架的原因 但不知道能用spring框架做什么 總而言之 還是繼續學吧。
我用的編譯器是Window10的idea 里面自帶Spring項目 因為看別人的博客吃了很多苦 在這里先說清楚 以免誤人子弟
博客講述方式將其代碼為主 所有的代碼都可以在我的github中找到(https://github.com/12Dong/learn-spring)
sprin配置可選方案
- 自動化配置
- java配置
- xml配置
后兩者是顯示的 邏輯關系很明顯就能看出來
自動化配置
Spring從兩個角度來實現自動化配置
- 組件掃描(ComponentScan):Spring會自動發現應用上下文中所創建的bean
- 自動裝配(Autowiring):Spring自動滿足bean之間的依賴
自動化配置樣例
實現·CompactDisc接口
package soundsystem;
public interface CompactDisc {
void play();
}
用一個類實現這個接口
package soundsystem;
import org.springframework.stereotype.Component;
@Component
public class SgtPeppers implements CompactDisc{
private String title = "舞動青春";
private String artist = "廣播操";
public void play(){
System.out.print("Playing "+title+" by "+ artist);
}
}
Component 配件注解 表明將告知Spring要為這個Component創建Bean
組件掃描默認是不開啟的 所以必須顯式開啟組件掃描
所以創建CDConfig.java進行配置
開啟組件掃描
package soundsystem;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class CDPlayerConfig {
//這里沒有任何顯式配置
//在接下來的java配置這里將添加配置關系
}
如果沒有其他配置的話 @Component 將默認掃描這個java文件所在package 查找帶0有@Component的類
此外還可以用xml開啟組件掃描 這里就不加累述
接下來就是困擾我將近兩天的Test測試框架了 我會單開一篇來講述我在配置Junit時遇到的問題
package soundsystem;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
@Autowired
private CompactDisc cd;
@Test
public void cdShouldNotBeNull(){
assertNotNull(cd);
}
}
然后就出現的結果是這樣子 no errors
通過為Bean添加注解實現自動裝配
package explictUse.soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
@Autowired(required = false)
/*
不管是構造器 或者setter方法還是其他方法
Spring都會嘗試滿足方法參數上的申明的依賴
假如只有一個bean匹配依賴需求的話 那么這個bean將會被裝配進來
如果沒有匹配的bean 那么在應用上下文創建的時候
Spring會拋擲一個異常 為了避免這種異常 可以將Autowired設置為false
*/
public CDPlayer(CompactDisc cd){
this.cd = cd;
}
public void setCompactDisc(CompactDisc cd){
this.cd = cd;
}
public void play(){
cd.play();
}
}
這里可以看出CDPlayer需要組合一個CompactDisc類 同樣我們也可以使用自動裝配為其配置compactDisc這個對象
驗證自動裝配
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.SystemOutRule;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
@Rule
public final SystemOutRule systemOutRule = new SystemOutRule().enableLog();
@Autowired
private CompactDisc cd;
@Autowired
private MediaPlayer player;
@Test
public void cdShouldNotBeNull(){
assertNotNull(cd);
}
@Test
// public void play(){
// player.play();
// assertEquals("Playing 舞動青春"+" by 廣播操\n",systemOutRule.getLog());
public void writesTextToSystemOut() {
player.play();
assertEquals("Playing 舞動青春 by 廣播操", systemOutRule.getLog());
}
}
在這里寫的原書上略有不同 原書上的
import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
在我的編譯器中報錯了
上網查證得知原庫無法使用
所以更為我用的方法
另外多次嘗試發現如果加了換行符 就匹配失敗 我也不知道為什么
結果圖如下
通過java代碼裝配bean
修改CDPlayerConfig中的代碼
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDPlayerConfig {
@Bean
public CompactDisc segPeppers(){
return new SgtPeppers();
}
// @Bean
// public CDPlayer cdPlayer(CompactDisc compactDisc){
// return new CDPlayer(compactDisc);
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc){
CDPlayer cdPlayer = new CDPlayer(compactDisc);
cdPlayer.setCompactDisc(compactDisc);
return cdPlayer;
}
}
Test驗證
通過java配置config可以用一些常見的java代碼實現 比如說setter函數之類的
通過xml裝備bean
xml在已擁有Spring自動配置和基于Java配置的情況不多常用 學習xml多是維護已有的xml配置
spring框架中使用.xml后綴文件來代替JavaConfig的配置java文件
書上實例 BlankDisc中擁有原本屬性之外 還多一個list容器
<?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:c = "http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--<bean id="compactDisc" class="xmlExplictUser.soundsystem.BlankDisc">-->
<!--<constructor-arg value = "舞動青春" />-->
<!--<constructor-arg value = "廣播操"/>-->
<!--</bean>-->
<!--<bean id = "compactDisc" class="xmlExplictUser.soundsystem.BlankDisc"-->
<!--c:_0 ="舞動青春"-->
<!--c:_1="廣播操" />-->
<bean id="compactDisc" class="xmlExplictUser.soundsystem.BlankDisc">
<constructor-arg value="廣播操"/>
<constructor-arg value="廣播臺"/>
<constructor-arg>
<list>
<value>舞動青春</value>
<value>時代在召喚</value>
<value>初生的太陽</value>
</list>
</constructor-arg>
</bean>
</beans>
Test測試一下
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import xmlExplictUser.soundsystem.BlankDisc;
public class BlankDiscTest {
@Test public void instanceSpring(){
AbstractApplicationContext context = new ClassPathXmlApplicationContext("xmlExplictUserBean.xml");
BlankDisc compactDisc = (BlankDisc)context.getBean("compactDisc");
compactDisc.play();
// context.close();
}
}
混合配置
通過java+xml配置依賴關系
package xmlExplictUser.soundsystem;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDConfig {
@Bean
public CompactDisc compactDisc(){
return new SgtPeppers();
}
}
有點蒙圈... ...等清醒一點再寫