JavaWeb筆記(24)-spring框架基礎

  1. spring框架
1. Spring是分層的Java SE/EE應用 full-stack輕量級開源框架
    以IoC(Inverse Of Control:反轉控制)和AOP(Aspect Oriented Programming:面向切面編程)爲內核
    提供了展現層Spring MVC和持久層Spring JDBC以及業務層事務管理等衆多的企業級應用技術
    還能整合開源世界衆多著名的第三方框架和類庫,逐漸成爲使用最多的Java EE企業應用開源框架
2. Spring優勢:
    a. 方便解耦,簡化開發:
        降低程序之間的依賴
        應該做到編譯期不依賴,運行期才依賴
        例如:
            //此方式註冊驅動如果沒有mysql-jar包,編譯期報錯
            DriverManager.registerDriver(new com.mysql.jdbc.Driver());
            //使用Class註冊驅動如果沒有mysql-jar包,運行期拋出異常
            Class.forName("com.mysql.jdbc.Driver");
    b. AOP編程的支持
    c. 聲明式事務的支持
    d. 方便程序測試
    e. 方便集成各種框架
    f. 降低JavaEE API使用難度
    g. Java源碼是經典的學習範例
3. 程序的耦合:
    a. 程序間的依賴關係:程序的編譯依賴於其他的程序
        1. 類之間的依賴
        2. 方法之間的依賴
    b. 解耦思想:
        1. 使用反射來創建對象,而避免使用new關鍵字
        2. 通過讀取配置文件來獲取要創建的對象的全限定類名
    c. 開發中應用:
        1. 創建工廠類來生產Bean對象:
            Bean在計算機英語中表示可重用組件
        2. JavaBean:
            JavaBean指用Java語言編寫的可重用組件
            JavaBean範圍遠大於實體類
        3. 需要一個配置文件來配置需要生產的Bean對象
            配置內容:唯一標識=全限定類名(key=value)
        4. 通過讀取配置文件配置的內容,反射創建對象
            配置文件可以使用xml或properties文件
            Object obj = Class.forName(beanPath).newInstance();
                * 每次調用newInstance方法都會調用一次默認構造函數
                * 此時創建的對象形式爲多例的
        5. 工廠類的構建:
            * 創建一個靜態私有的Properties對象用於加載配置文件
            * 創建一個靜態容器Map對象用於保存配置文件中要求的對象
            *static靜態代碼塊中讀取配置文件,利用反射創建對象,將配置文件中的key和新創建的對象存儲Map容器
            * 在靜態方法中返回Map容器中早已創建好的對象
            * 由於靜態代碼塊僅在類加載時執行一次,因此該工廠調用成員方法創建的對象都是同一個,對象爲單例形式
        6. 使用工廠生產Bean對象先決條件:
            業務層和持久層中幾乎可以改變的成員變量
  1. IoC控制:Inverse Of Control 反轉控制
1. 原始創建對象形式:
    由app尋找資源,然後創建對象(new形式)
2. 控制反轉創建形式:
    由app向工廠索要對象,工廠控制資源(工廠類形式)
    將原本自主創建對象的權力交予工廠,即控制反轉。包括依賴注入和依賴查找
  1. 使用spring的IOC解決程序耦合
1. 下載解壓spring framework:
    spring-framework-5.0.2.RELEASE-dist
2. 導入相關spring相關jar包:
    spring-aop-5.0.2.RELEASE.jar        --      基於註解開發的必備jar包
    spring-beans-5.0.2.RELEASE.jar      --      中間4個爲核心容器的jar包
    spring-context-5.0.2.RELEASE.jar
    spring-core-5.0.2.RELEASE.jar
    spring-expressoin-5.0.2.RELEASE.jar
    spring-jcl-5.0.2.RELEASE.jar        --      集成了apache的日誌組件做成了自己的jar包
    使用座標定位時僅需要定位spring-context即可:
        * 當前工程依賴於spring-context
        * spring-context依賴於spring-beans,spring-aop,spring-expression,spring-core
        * spring-aop依賴於spring-beans,spring-core
        * spring-beans依賴於spring-core
        * spring-expression依賴於spring-core
        * spring-core依賴於spring-jcl
3. 創建xml配置文件,並導入約束:
    /resource/bean.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.xsd">
        <!--配置相關信息-->
    </beans>
4. 使用bean標籤將對象的創建交給框架:
    <bean id="唯一標識key" class="需要創建的對象的全限定類名"></bean>
5. 獲取spring核心容器,並根據id獲取創建的對象:
    //獲取核心容器對象
    ApplicationContext coreObj = new ClassPathXmlApplicationContext("配置文件名(bean.xml)")
    //依據id獲取Bean對象
    E element = (E) coreObj.getBean("唯一標識id");
    //E element = (E) coreObj.getBean("唯一標識id", E.class);
    * 獲取核心容器的三種形式:
        1. ClassPathXmlApplicationContext:僅能加載類路徑下的配置文件
        2. FileSystemXmlApplicationContext:可以加載任意磁盤路徑下的配置文件(需要有訪問權限)
        3. AnnotationConfigApplicationContext:用於讀取註解創建容器
    * 核心容器的兩個接口:
        1. ApplicationContext:單例對象適用,但是可以根據配置設置立即或延遲,因此開發更爲常用
            在構建核心容器時,創建對象爲立即加載方式。即,讀取完配置文件後,立即創建所有配置中的對象
        2. BeanFactory:多例對象適用
            在構建核心容器時,創建對象爲延遲加載方式。即,僅由id獲取對象時創建該對象
6. spring對Bean的管理細節:
    a. 創建bean的三種方式:
        1. 使用默認構造函數創建對象:
            在spring的配置文件中使用bean標籤,配置id和class屬性,且沒有其他屬性和標籤,調用默認構造函數創建
                <bean id="唯一標識key" class="需要創建的對象的全限定類名"></bean>
            如果此時類中沒有默認構造函數(重寫了帶參構造函數但是沒有重寫默認構造函數),則不能創建bean對象
        2. 使用其他類中的方法創建對象:
            在spring的配置文件中使用bean標籤,配置id,factory-bean,factory-method屬性,調用工廠類中方法創建
                <bean id="唯一標識key" class="創建對象的工廠的全限定類名"></bean>
                <bean id="唯一標識key" factory-bean="工廠唯一標識id" factor-method="創建對象的方法"></bean>
        3. 使用其他類中的靜態方法創建對象:
            在spring的配置文件中使用bean標籤,配置id,class,factory-method屬性,調用工廠類中靜態方法創建
                <bean id="唯一標識key" class="工廠全限定類名" factor-method="創建對象的靜態方法"></bean>
    b. bean對象的作用範圍:
        1. 默認情況下,bean標籤創建對象的形式是單例的
        2. 通過bean標籤的scope屬性來指定bean的作用範圍:
            * singleton:單例的(默認值)
            * prototype:多例的
            * request:作用於web應用的請求範圍
            * session:作用於web應用的會話範圍
            * global-session:作用於集羣環境的會話範圍(全局會話範圍),當不是集羣範圍時,等同於session範圍
    c. bean對象的生命週期:
        1. 單例對象:
            生命週期與容器相同:容器創建時創建,容器銷燬時銷燬
            調用ClassPathXmlApplicationContext的close方法銷燬容器
        2. 多例對象:
            生命週期:使用對象時spring框架創建,當對象長時間沒有使用且無其他對象引用時有java垃圾回收機制回收
7. spring中的依賴注入:
    a. 依賴關係管理:
        表示層調用業務層,業務層調用持久層這是必然會出現的
        於是將調用間的對象創建交由spring,這種依賴關係有spring管理
        我們只需要在配置文件中說明,在當前類中需要使用其他類的對象,其他類的對象有spring提供
        依賴關係的維護稱爲:依賴注入
    b. 能夠注入的數據:
        1. 基本類型和String
        2. 其他bean類型(在配置文件中或者註解配置過的bean)
        3. 複雜類型/集合類型
    c. 注入方式:
        1. 使用構造函數
            被注入的類中重寫了帶參構造函數時,在bean標籤的配置內部加入constructor-arg標籤
            <bean id="唯一標識key" class="需要創建的對象的全限定類名">
                <constructor-arg></constructor-arg>
                <!--
                    constructor-arg標籤中的屬性:
                    * type:用於指定要注入的數據的數據類型,該數據類型也是構造函數中某個或某些參數的類型
                    * index:用於指定注入數據在構造函數中參數的索引,從0開始
                    * name:用於指定注入數據在構造函數中的名稱                              (常用形式)
                    =======================以上3個屬性用於確定給構造函數中哪個參數賦值==================
                    * value:指定參數注入的值,僅限基本類型和String類型
                    * ref:用於引用關聯的bean對象,僅限IOC容器中配置過的對象
                -->
            </bean>
            例如:
                當需要注入的參數爲Date類型數據時,並不能直接使用value賦值一個字符串
                而需要另外定義一個bean對象,反射創建一個Date對象,用constructor-arg的ref屬性引用創建的Date對象
                <bean id="now" class="java.util.Date"></bean>
                <bean id="xxx" class="xxx.xxx.xxx">
                    <constructor-arg name="birthday" ref="now"></constructor-arg>
                </bean>
            優勢:
                由於沒有默認構造函數,所以創建對象時,配置注入參數的操作是必須的,否則無法創建對象
            劣勢:
                改變了bean對象的實例化方式,如果不使用該bean對象也同樣需要配置參數注入
        2. 使用set方法
            被注入的類中必須含有參數的set方法,可以不寫get方法。在bean標籤內部使用property標籤
            <bean id="唯一標識key" class="需要創建的對象的全限定類名">
                <property></property>
                <!--
                    property標籤中的屬性:
                    * name:用於指定注入數據在set方法中的屬性名稱
                    * value:指定參數注入的值,僅限基本類型和String類型
                    * ref:用於引用關聯的bean對象,僅限IOC容器中配置過的對象
                -->
            </bean>
            優劣與構造方法創建相反
            複雜數據類型注入:
                * 給List結構的參數注入:
                    在property內部有子標籤list,set,array,在通過子標籤的子標籤<value></value>進行元素賦值
                    <property name="myList">
                        <list>
                            <value>索引爲0的值</value>
                            <value>索引爲1的值</value>
                            ...
                        </list>
                    </property>
                * 用於給map結構的參數注入:
                    在property內部有子標籤map,propos,在通過子標籤的key和value爲元素賦鍵值
                    <property name="myMap">
                        <map key="鍵" value="值"></map>
                    </property>
                * 相同結構的注入操作標籤可以互換,即List可以使用set/list/array標籤都行
        3. 使用註解
  1. 舉例:使用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.xsd">
    <!-- 配置Service -->
    <bean id="accountService" class="cn.mysilent.service.impl.AccountServiceImpl">
        <!-- 注入dao -->
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--配置Dao對象-->
    <bean id="accountDao" class="cn.mysilent.dao.impl.AccountDaoImpl">
        <!-- 注入QueryRunner -->
        <property name="runner" ref="runner"></property>
    </bean>

    <!--配置QueryRunner,爲了使每個查詢不相互干擾,配置該對象的創建爲多例prototype-->
    <!--如果QueryRunner是單例對象,則面臨多個dao使用時,可能引發線程安全問題-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!--注入數據源-->
        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>

    <!-- 配置數據源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--連接數據庫的必備信息-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
        <property name="user" value="用戶名"></property>
        <property name="password" value="密碼"></property>
    </bean>
</beans>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章