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