上一章對Spring作一個快速入門的教程,其中只是簡單的提到了IOC的特性。本章便對Spring的IOC進行一個詳解。主要從三個方面開始:基於xml文件的Bean配置,基於註解的Bean配置和IOC容器Bean的生命週期。java
首先是applicationContext.xml文件,這但是核心文件。
配置一個bean,須要一個id去惟一標識它,用class指定Bean對象的路徑,做用域默認是單例。
經過prototype進行屬性賦值,name是屬性名,value是值,也能夠用ref引用對象,用list,map設置集合。
用SpEL表達式語言賦值,用p命名空間簡化賦值,用繼承和依賴簡化代碼。spring
<?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:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 配置一個 bean bean中有一個id,且id是惟一的。若不指名則爲該類的類名並首字母小寫。 property 中有一個name,其name就是生產了setter方法的屬性,value即是其值。 --> <!-- Bean 的做用域 singleton:單例,默認值,容器初始化建立bean實例,在整個生命週期內只建立一個bean。 prototype:原型,容器初始化不建立bean實例,每次請求的時候會建立一個新的bean --> <bean id="entity" class="com.itdragon.spring.my.Entity" scope="prototype"> <!-- 屬性賦值 屬性注入使用 <property> 元素, 使用 name 屬性指定 Bean 的屬性名稱,value 屬性或 <value> 子節點指定屬性值 --> <property name="intValue" value="1"></property> <!-- 引用bean 細節: 1. 用ref 是引用外部bean 2. 也能夠直接寫在當前bean裏面,這就是內部bean, 內部bean是不能被外部引用 --> <property name="spELEntity" ref="spELEntity"></property> <!-- 構造器注入 構造器注入在 <constructor-arg> 元素裏聲明屬性, <constructor-arg> 中沒有 name 屬性,按照構造器參數順序賦值 細節: 1. 也能夠用index(按索引匹配入參),和type(按類型匹配入參)去指定賦值。其實是沒有必要的 2. 使用構造器注入的前提是 entity 被初始化。 3. 特殊字符,須要用 <![CDATA[內容]]> 這屬於xml語法 --> <constructor-arg value="1.1" /> <constructor-arg > <value><![CDATA[<ITDragon>]]></value> </constructor-arg> <property name="listValue"> <list> <value>歡迎閱讀</value> <value>ITDragon</value> <value>的博客!</value> </list> </property> <property name="mapValue"> <map> <entry key="one" value="1"></entry> <entry key="two" value="2"></entry> </map> </property> </bean> <!-- SpEL 表達式語言, #{…} 做爲定界符, 操做和java類似--> <bean id="spELEntity" class="com.itdragon.spring.my.SpELEntity"> <property name="intSpel" value="#{1}"></property> <property name="floatSpel" value="#{entity.intValue + 0.2}"></property> <property name="stringSpel" value="#{'Spring4基礎教程'}"></property> <property name="bSpel" value="#{2 >= 1}"></property> </bean> <!-- 使用 p 命名空間 給Entity 對象 的intValue 字段設置 爲2 ,根據名稱匹配SpEL對象 自動裝配 autowire (不經常使用) byName(根據名稱自動裝配): 必須將目標 Bean 的名稱和屬性名設置的徹底相同.反之不能 byType(根據類型自動裝配): 若 IOC 容器中有多個與目標 Bean 類型一致的 Bean. 在這種狀況下, 不能執行自動裝配. --> <bean id="entity2" class="com.itdragon.spring.my.Entity" p:intValue="2" autowire="byName" /> <!-- 繼承 依賴 若是 被繼承的bean 不想被繼承,則要加上 abstract="true" 依賴:若是被依賴的bean,沒有實例化,則會報錯。若是有多個依賴需用","分開 --> <bean id="entity3" class="com.itdragon.spring.my.Entity" parent="entity" depends-on="spELEntity" /> <!-- 使用外部屬性文件 在Spring操做數據庫的時候再講 --> </beans>
實體類Entity和SpELEntity數據庫
import java.util.List; import java.util.Map; public class Entity { private int intValue; private float floatValue; private String stringValue; private SpELEntity spELEntity; private Map<String, Object> mapValue; private List<Object> listValue; public Entity() { } public Entity(float floatValue, String stringValue) { this.floatValue = floatValue; this.stringValue = stringValue; } public int getIntValue() { return intValue; } public void setIntValue(int intValue) { this.intValue = intValue; } public float getFloatValue() { return floatValue; } public void setFloatValue(float floatValue) { this.floatValue = floatValue; } public String getStringValue() { return stringValue; } public void setStringValue(String stringValue) { this.stringValue = stringValue; } public SpELEntity getSpELEntity() { return spELEntity; } public void setSpELEntity(SpELEntity spELEntity) { this.spELEntity = spELEntity; } public Map<String, Object> getMapValue() { return mapValue; } public void setMapValue(Map<String, Object> mapValue) { this.mapValue = mapValue; } public List<Object> getListValue() { return listValue; } public void setListValue(List<Object> listValue) { this.listValue = listValue; } @Override public String toString() { return "Entity [intValue=" + intValue + ", floatValue=" + floatValue + ", stringValue=" + stringValue + ", spELEntity=" + spELEntity + ", mapValue=" + mapValue + ", listValue=" + listValue + "]"; } }
public class SpELEntity { private int intSpel; private float floatSpel; private boolean bSpel; private String stringSpel; public int getIntSpel() { return intSpel; } public void setIntSpel(int intSpel) { this.intSpel = intSpel; } public float getFloatSpel() { return floatSpel; } public void setFloatSpel(float floatSpel) { this.floatSpel = floatSpel; } public boolean isbSpel() { return bSpel; } public void setbSpel(boolean bSpel) { this.bSpel = bSpel; } public String getStringSpel() { return stringSpel; } public void setStringSpel(String stringSpel) { this.stringSpel = stringSpel; } @Override public String toString() { return "SpELEntity [intSpel=" + intSpel + ", floatSpel=" + floatSpel + ", bSpel=" + bSpel + ", stringSpel=" + stringSpel + "]"; } }
測試Main方法。首先要建立一個容器,而後經過bean的id獲取到實例,這樣就能夠開始相關的操做。其中entity,entity2,entity3對應三塊不一樣的知識點。express
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { /** * ClassPathXmlApplicationContext:從 類路徑下加載配置文件,建議用該方法 * FileSystemXmlApplicationContext: 從文件系統中加載配置文件 */ // 1. 建立 Spring 的 IOC 容器 ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); /** * entity 屬性注入,構造器注入,對象引用,集合,SpEL,(重點) * entity2 自動裝配和P命名空間 * entity3 繼承和依賴,做用域 */ // 2. 從 IOC 容器中獲取 bean 的實例 Entity entity = (Entity) ctx.getBean("entity"); // 3. 使用 bean System.out.println(entity.toString()); // System.out.println(ctx.getBean("entity") == ctx.getBean("entity")); 使用 prototype 打印的是false ctx.close(); } }
Entity [intValue=1, floatValue=1.1, stringValue=<ITDragon>, spELEntity=SpELEntity [intSpel=1, floatSpel=1.2, bSpel=true, stringSpel=Spring4基礎教程], mapValue={one=1, two=2}, listValue=[歡迎閱讀, ITDragon, 的博客!]]
相對於xml的配置,註解的方式顯得異常簡單。主要分兩個步驟
第一步:在applicationContext.xml文件設置掃描包的範圍segmentfault
<?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:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" 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/util http://www.springframework.org/schema/util/spring-util-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置自動掃描指定目錄下的包 resource-pattern="xxx/*.class" 屬性過濾特定的類 --> <context:component-scan base-package="com.itdragon.spring.my" > <!-- annotation 是針對指定的類 和 assignable 是針對全部繼承或者擴展該類的類--> <!-- context:exclude-filter 只排除expression裏面的內容 <context:exclude-filter type="annotation" expression=""/> --> <!-- context:include-filter 只包含expression裏面的內容 需配合 use-default-filters="false"(默認是true) 一塊兒使用 <context:include-filter type="annotation" expression=""/> --> </context:component-scan> </beans>
第二步:在對象上用註解。這四幾個註解的做用同樣,只是爲告終構清晰,取的名字不一樣罷了。
使用方法很簡單:直接在類上加註解便可。無參數的狀況,bean的id默認是小寫字母開頭的類名。也能夠指定參數@Commponent("指定參數"),那bean的id就是指定參數。
@Component: 基本註解, 標識了一個受 Spring 管理的組件
@Respository: 標識持久層組件
@Service: 標識服務層(業務層)組件
@Controller: 標識表現層組件app
public interface AnnoRepository { public void hello(); }
import org.springframework.stereotype.Repository; @Repository public class AnnoRepositoryImp implements AnnoRepository{ @Override public void hello() { System.out.println("AnnoRepository : hello!"); } }
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class AnnoService { @Autowired private AnnoRepository annoRepository; public void hello() { System.out.println("AnnoService : hello!"); annoRepository.hello(); } }
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @Controller public class AnnoController { @Autowired private AnnoService annoService; public void execut() { System.out.println("AnnoController : hello !"); annoService.hello(); } }
這裏還有一個註解Autowired, <context:component-scan> 元素會自動組件裝配被Autowired修飾的對象。
測試類:雖然applicationContext.xml中沒有annoController的bean配置,但咱們有註解!ide
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); AnnoController annoController = (AnnoController) ctx.getBean("annoController"); annoController.execut(); ctx.close(); } }
AnnoController : hello ! AnnoService : hello! AnnoRepository : hello!
有沒有以爲基於註解的bean配置比基於xml的bean配置簡單不少。測試
step1 實例化,經過構造器建立 Bean 實例
step2 賦值,爲 Bean 的屬性設置值
step3 init-method,調用 Bean 的初始化方法(init-method)
step4 destroy-method,當容器關閉時, 調用 Bean 的銷燬方法(destroy-method)this
以上代碼都是筆者親測可用的,不要嫌麻煩,麻煩是學很差的,若是有什麼問題和建議能夠留言,我會及時處理。http://blog.csdn.net/qq_19558...spa