天天看點

Java 之 Spring 架構概述Spring建立 Spring 流程

Spring

Spring是一個開放源代碼的設計層面架構
他解決的是業務邏輯層和其他各層的松耦合問題,是以它将面向接口的程式設計思想貫穿整個系統應用。
Spring是于 年興起的一個輕量級的Java 開發架構,由Rod Johnson建立。
簡單來說,Spring是一個分層的JavaSE/EE full-stack(一站式) 輕量級開源架構。
把它了解為對象的管家,幫忙管理項目中用到的對象
其實說白了就是容器
           

特點

1.開源
2.輕量級(體積小)
3.分層架構(按需添加)
4.一站式(對目前流行的架構支援非常高)
5.IOC
6.DI
           
使用 Spring 帶來的好處
1.降低複雜性
2.松耦合
3.高性能
4.易測試 Junit
5.聲明式事務
           

建立 Spring 流程

下載下傳所需 jar 包
導入核心包 beans context expression core logging(日志包)
建立編寫配置檔案
    建立對象交給 Spring 來管理
建立 applicationContex容器
通過 getBean 來擷取到對象,如果對象不為空,則 Spring 搭建成功
           
public class HelloSpring {
    public static void main(String[] args) {
        // 從容器中擷取被管理的對象
        // 1.建立容器
        // ClassPathXmlApplicationContext("classpath:applicationContext.xml"); 
        // 使用指定配置檔案,classpath 可忽略不寫
        @SuppressWarnings("resource")
        ApplicationContext applicationContext = new 
        ClassPathXmlApplicationContext("applicationContext.xml");
        // 2.從容器中擷取 bean
        Person person = (Person) applicationContext.getBean("person");
        // 檢視對象是否擷取成功
        System.out.println(person);
    }
}


<?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">

    <!-- 讓 Spring 管理 Person 的對象,對象名字叫做 person
        class:全限定類名,要被管理的類的名字
        name:被管理對象的名稱
     -->
    <bean class="com.xxx.Person" name="person">
        <!-- set 注入
            必須提供 set 方法
            value 屬性用于注入基礎資料類型
            ref 屬性用于注入引用資料類型
             -->
        <property name="name" value="張三"></property>
        <property name="age" value="20"></property>
        <property name="car" ref="car"></property>
    </bean>
    <bean class="com.xxx.Car" name="car">
        <property name="name" value="布加迪威龍"></property>
        <property name="color" value="鎏金"></property>
    </bean>
</beans>
           

核心思想 IOC

inverse of control(反轉控制)
說白了就是把對象的建立反轉(交給) Spring 來管理
不需要手動去建立對象,需要調用時,從 Spring 擷取對象
實作原理:通過反射 + 配置檔案
Class class = Class.forName("com.xxx.Person");
Object object = class.newIncetance();
context.put("person", object);

context.get("person");
           

DI技術

dependency injection
   依賴         注入
類 A 中需要類 B 提供的功能
稱為 A 依賴 B
例如: service 依賴 DAO
UserService
UserDao dao = new UserDaoImplForJDBC();
UserDao dao = new UserDaoImplForHibernate();
使用 Spring 之後 
UserDao dao = context.getBean("userDaoImpl");
不需要修改源代碼就能實作元件的切換

注入:從外部把需要的對象放到内部就叫注入
UserService
private UserDao dao;
set/get 方法

依賴注入最終的目的就是提高程式的擴充性,盡可能的不去修改源代碼
           

bean 的建立方式

1.構造函數建立(預設的)
<bean name="person4" class="com.lanou3g.Person">
    <!-- name 指定參數名,需要與構造函數一緻 -->
    <!-- index 指定參數放到哪一個位置
        使用場景:當多個構造函數參數相同,但是順序不同時,調用 -->
    <!-- type 指定參數的類型
        使用場景:當多個構造函數參數順序相同,但是資料類型不同時,調用 -->
    <constructor-arg name="car" ref="car" index="0"></constructor-arg>
    <constructor-arg name="name" value="0123" type="Integer"></constructor-arg>
    <constructor-arg name="age" value="20"></constructor-arg>
</bean>
           
2.靜态工廠建立(調用指定的靜态方法擷取 bean)
<!-- 到 PersonFactory 中調用 getPerson 的靜态方法來擷取對象,并放入容器中
    如果使用預設的建立方式, Spring 會到對應類中找到空參數的構造函數
    如果指定了 factory-method, 則 Spring 會到類中找到指定的靜态方法執行
    class 指定類型可以與 bean 的類型不一緻
 -->
<bean name="person2" class="com.xxx.PersonFactory"  factory-method="getPerson">
    <property name="name" value="王五"></property>
</bean>
           
3.執行個體工廠建立(調用執行個體方法擷取 bean)
<!-- 通過執行個體工廠方法建立
    到 PersonFactory 的某個對象中找到 getPerson2的方法,擷取傳回對象
 -->
<bean name="personFactory" class="com.lanou3g.PersonFactory"></bean>
<bean name="person3" class="com.lanou3g.PersonFactory" 
    factory-method="getPerson2" factory-bean="personFactory">
    <property name="name" value="趙六"></property>
</bean>
           

依賴注入的四種方式

set 注入(就是通過 set 方法,是以必須有 set 方法)
<bean class="com.lanou3g.Person" name="person">
    <!-- set 注入
        必須提供 set 方法
        value 屬性用于注入基礎資料類型
        ref 屬性用于注入引用資料類型
         -->
    <property name="name" value="張三"></property>
    <property name="age" value="20"></property>
    <property name="car" ref="car"></property>
</bean>
<bean class="com.lanou3g.Car" name="car">
    <property name="name" value="布加迪威龍"></property>
    <property name="color" value="鎏金"></property>
</bean>
           
2.構造函數注入
<bean name="person4" class="com.lanou3g.Person">
    <!-- name 指定參數名,需要與構造函數一緻 -->
    <!-- index 指定參數放到哪一個位置
        使用場景:當多個構造函數參數相同,但是順序不同時,調用 -->
    <!-- type 指定參數的類型
        使用場景:當多個構造函數參數順序相同,但是資料類型不同時,調用 -->
    <constructor-arg name="car" ref="car" index="0"></constructor-arg>
    <constructor-arg name="name" value="0123" type="Integer"></constructor-arg>
    <constructor-arg name="age" value="20"></constructor-arg>
</bean>
           
3.<:p 命名空間
<?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"
    xmlns:p="http://www.springframework.org/schema/p"><!-- p 命名空間需要先引入命名空間 -->

<!-- p 命名空間
        實質上還是調用 set 方法,隻是為了簡化書寫 -->
    <bean name="person5" class="com.lanou3g.Person" p:name="老王" p:age="50" p:car-ref="car"></bean>
           
4.SpEL 表達式
<!-- SpEL 注入
    Spring 的表達式語言,能夠實作一些簡單的邏輯
    與 JSP 的 EL 一個性質 -->
<bean name="person6" class="com.lanou3g.Person">
    <!-- 找到一個叫 person 的對象,調用 getName 方法擷取資料 -->
    <property name="name" value="#{person.name}"></property>
    <property name="age" value="#{person5.age}"></property>
    <property name="car" ref="car"></property>
</bean>
           

ApplicationContext 的兩個實作類

ClassPathXMLApplicationContext 用于加載 Class 路徑下的配置檔案
FileSystemXMLApplicationContext 用于加載系統路徑下的配置檔案

public class HelloSpring {
    public static void main(String[] args) {
        // ApplicationContext 接口有兩個實作類

        // 從類路徑下加載配置檔案
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        System.out.println(applicationContext.getBean("person"));
        // 從系統路徑下加載配置檔案
        ApplicationContext applicationContext2 = new FileSystemXmlApplicationContext("file:/Users/eclipse-workspace/spring/src/beans.xml");
        System.out.println(applicationContext2.getBean("person"));
    }
}
           

兩種容器

Spring 提供兩種容器 
1.BeanFactory(已經過時了) Spring 架構最古老的接口 
僅定義了實作 IOC DI 基礎功能的接口
特點:擷取 bean 時才會建立對應 bean 以前的硬體裝置資源匮乏 
2.ApplicationContext 功能更加強大
特點:一旦加載配置檔案就全部建立出來
           

bean 元素的屬性

scope
    singleton   單例(預設)
    prototype   多例
    request     與 request 生命周期一緻
    session     與 session 生命周期一緻

scope 屬性用來指定 bean 的作用域
        singleton: 單例,該 bean 對象在 Spring 中隻存在一個 *最常用
        (注意:在和 struts2整合時,Action 對象不能設定為單例)
        prototype: 多例,每次 getBean 是都會建立新的 bean *
        request 和 session 對象的生存時間與 session 或 request 一緻
           

生命周期方法

init-method     對象建立完立即執行
destroy-method  對象銷毀前執行
           
id 與 name 功能是一樣的
id 不能重複,不能用特殊字元
name 可以重複,可以有特殊字元
           

複雜類型的注入

array       使用 array 子标簽
            例如:<array>
                    <value>123</value>
                </array>
list        使用 list 子标簽(同 array)
            例如:<list>
                    <value>456</value>
                </list>
map         使用 entry 子标簽
            例如:<map>
                    <entry key="name" value="qaz1"></entry>
                    <entry key="age" value="10"></entry>
                    <entry key-ref="引用類型" value="這是一個 bean"></entry>
                    <entry key="這是一個 bean" value-ref="引用類型"></entry>
                </map>
properties  使用 props 子标簽
            例如:<props>
                    <prop key="jdbcDriver">jdbc:mysql://localhost:3306/MyDB</prop>
                    <prop key="user">root</prop>
                    <prop key="password">123456</prop>
                </props>
           
<bean id="collectionBean" class="com.lanou3g.CollectionBean">
    <!-- 元素隻有一個值,可以直接使用 value 注入 -->
    <property name="array">
        <array>
            <value>jack</value>
            <value>rose</value>
            <value>john</value>
        </array>
    </property>
    <property name="list">
        <list>
            <value>1</value>
            <value>2</value>
            <value>3</value>
        </list>
    </property>
    <!-- 元素隻有一個時,也不能用 value 注入 -->
    <property name="map">
        <map>
            <!-- 使用 entry 标簽來指定鍵值對 -->
            <entry key="name" value="qaz1"></entry>
            <entry key="age" value="10"></entry>
            <entry key-ref="abean" value="這是一個 bean"></entry>
            <entry key="這是一個 bean" value-ref="abean"></entry>
        </map>
    </property>
    <property name="properties">
        <props>
            <prop key="jdbcDriver">jdbc:mysql://localhost:3306/MyDB</prop>
            <prop key="user">root</prop>
            <prop key="password">123456</prop>
        </props>
    </property>
</bean> 
<bean name="abean" class="com.lanou3g.CollectionBean"></bean>
           

配置檔案的子產品化

當一個配置檔案内容太多時,可以按照功能子產品劃分
1.在建立容器時,傳入多個字元串對象(配置檔案名)
ApplicationContext applicationContext 
= new ClassPathXmlApplicationContext("beans.xml", "applicationContext.xml");
2.在一個配置檔案中使用 import 标簽導入其他配置檔案
<import resource="classpath:applicationContext.xml"/>