Spring4 IOC詳解

Spring4 IOC詳解

上一章對Spring作一個快速入門的教程,其中只是簡單的提到了IOC的特性。本章便對Spring的IOC進行一個詳解。主要從三個方面開始:基於xml文件的Bean配置,基於註解的Bean配置和IOC容器Bean的生命週期。java


基於xml文件的Bean配置

首先是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, 的博客!]]

基於註解的Bean配置

相對於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配置簡單不少。測試


IOC容器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

20170923190228262

相關文章
相關標籤/搜索