Spring概念及IOC使用
Spring概述
1. Spring概念
Spring是分層的JavaSE/EE應用full-stack輕量級開源框架,以IOC(inverse Of Control,反轉控制)和AOP(Aspect Oriented Programming,面向切面程式設計)為核心,提供了展示層SrpingMVC和持久層SpringJDBC以及業務層事務管理等眾多企業級應用技術,還能整合開源世界眾多著名的第三方框架和類庫,主鍵成為使用最多的JavaEE企業級應用開發框架。
2017 年 9 月份釋出了 spring 的最新版本 spring 5.0 通用版(GA)
2. Spring的優勢
- 方便解耦,簡化開發
通過Spring提供的IOC容器,可以將物件間的依賴關係交由Spring進行控制,避免硬編碼所造成的過程程式耦合。使用者也不必再為單例模式類、屬性檔案解析等浙西很底層的需求編寫程式碼,從而更專注於上層的應用。
- AOP程式設計的支援
通過Spring的AOP功能,方便進行面向切面的程式設計,許多不容易用傳統OOP實現的功能可以通過AOP輕鬆應對。
- 宣告式事務的支援
可以將我們從單調煩悶的事務管理程式碼中解脫出來,通過宣告式方式靈活地進行事物的管理,提高開發的效率和質量。
- 方便程式的測試
可以用非容器依賴的程式設計方式進行所有測試工作,測試不再是昂貴的操作,而是隨手可 做的事情。
- 方便整合各種優秀框架
Spring 可以降低各種框架的使用難度,提供了對各種優秀框架(Struts、Hibernate、Hessian、Quartz 等)的直接支援。
- 降低 JavaEE API 的使用難度
Spring 對 JavaEE API(如 JDBC、JavaMail、遠端呼叫等)進行了薄薄的封裝層,使這些 API 的 使用難度大為降低。
- Java 原始碼是經典學習範例
Spring 的原始碼設計精妙、結構清晰、匠心獨用,處處體現著大師對 Java 設計模式靈活運用以 及對 Java 技術的高深造詣。它的原始碼無意是 Java 技術的最佳實踐的範例。
3. Spring體系結構
Core Container:物件容器
Beans,Core,Context,SpEL:Map物件,可以通過解耦的方式獲取物件。
IOC產生背景
1. 程式耦合:程式之間存在依賴關係
包括:類之間的耦合
方法間的耦合
三層架構實現的專案,耦合性太高。
程式解耦:降低程式間的依賴關係
開發中做到:編譯期不依賴,執行時才依賴。
類之間解耦思路:
-
- 通過反射建立物件,而避免使用new關鍵字
- 通過讀取配置檔案中的全限定類名,來獲取要建立物件的類名
2. IOC解決程式耦合
IOC(Inversion of Control, 控制反轉)把自主建立物件(new物件)的權利交由框架或工廠,框架通過注入的依賴進行依賴查詢,通過非面向物件程式設計的方式實現物件的建立,減少程式的耦合。
使用步驟:
- 建立容器配置檔案。
<?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"> <bean id="AccountService" class="com.spring.two.service.AccountServiceImpl"></bean> <bean id="AccountDao" class="com.spring.two.dao.AccountDaoImpl"></bean> </beans>
- 通過ApplicationContext獲取物件
public class IOCTest { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("bean.xml"); Account account=new Account(); AccountService service=context.getBean("AccountService", AccountService.class); service.saveAccount(account); } }
IOC細節
1. IOC相關類的繼承結構
2. ApplicationContext容器介面
實現了BeanFactory、ResourceLoader等介面。
ApplicationContext的實現類:通過配置內容建立容器。
ClassPathXmlApplicationContext: 載入類路徑下的配置檔案,建立容器;
FileSystemXmlApplicationContext: 載入磁碟路徑下的配置檔案,建立容器;
AnnotationConfigApplicationContext: 讀取註解,建立容器;
ApplicationContext介面 VS BeanFactory介面:
ApplicationContext:適用於單例物件
立即載入(預設):讀取完配置檔案後,建立配置檔案中的所有物件。物件被呼叫時,返回已創的物件。
可以通過配置檔案,改變物件的建立模式(單例,多例)。
BeanFactory:適用於多例物件
延遲載入:當物件d被需要時,通過配置檔案,建立物件。
3.<bean>標籤:用於容器建立物件
在xml中配置類標識和全限定類名的關係,ApplicationContext容器通過載入<bean>標籤,以非OOP的方式建立物件。
屬性:
id:物件在容器中的唯一標識。
class:物件的全限定類名
scope:物件的作用範圍。
init-method:初始化方法名
destroy-method:銷燬方法名
子標籤:
<constructor-age>:通過構造方法,注入依賴
<property>:通過set方法,注入依賴
scope屬性:容器物件的作用範圍。
a)singleton:預設的,建立單例物件。
生命週期:
出生:立即載入。容器一旦載入配置檔案,物件就隨之建立;
存活:只要容器存活,物件就存活;
死亡:容器銷燬,物件也死亡。
b) prototype: 建立多例物件。
生命週期:
出生:物件被使用時,由Spring框架建立;
存活:物件使用過程中一直存活;
死亡:物件長時間不使用並沒有別的物件引用時,由垃圾的回收期回收。
c)request: 作用於web應用的一次請求範圍,將物件儲存到request域中
d)session:作用於web應用的一次會話範圍,將物件儲存在session域中。
e)global-session:作用於叢集環境的會話範圍。
叢集環境:同一IP的所有伺服器中,一次會話中共享資料。
通過bean標籤建立物件的三種方式:
a) <bean id=””, class=””>: 使用類的預設建構函式建立物件,並存入Spring容器。
如果類中沒有預設建構函式,則物件無法建立
b) <bean id=””, class=”全限定類名”, factory-method=”方法”>:使用工廠的方法建立物件(某個類的方法建立物件,並存入core contrainer)
c) <bean id=””, class=”全限定類名”, factory-mehtod=”方法”>: 使用工廠的靜態方法建立物件(某個類的靜態方法建立物件,並存入spring容器)
4. 注入依賴
Spring通過IOC以非OOP的方式建立物件,降低程式間的耦合。
並且Spring維護類之間的依賴關係,即當類需要使用其他類的物件時,由Spring提供所依賴的物件,我們只需要在配置檔案中說明依賴的關係,這就稱為依賴注入。
依賴注入的型別:
- 基本型別和String:String會轉成需要的基本型別
- Bean型別(在配置檔案中或註解中配置過的Bean類)
- 複雜型別:陣列、List、Set、Map、Properties等
依賴注入的方式:
- 建構函式+<constructor-org>子標籤
- 在類中,依賴通過類建構函式的引數賦值。
- 在配置檔案中,通過<constructor-org>標籤注入依賴:
屬性:type: 注入資料的型別
index:注入資料的索引
name: 注入資料的引數名
value:要注入的基本型別或String型別的資料。
ref:要注入的bean物件。包括註解配置的或xml配置的bean物件
建構函式方法注入:
<bean id="AccountService2" class="com.spring.two.service.AccountServiceImpl2">
<constructor-arg name="name" value="neo"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="birthday"></constructor-arg>
</bean>
<bean id="birthday" class="java.util.Date"></bean>
建構函式:
public AccountServiceImpl2(String name, int age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
優點:Spring建立bean物件時,依賴都被注入,否則無法建立成功
缺點:改變了bean物件例項化的方式,所需依賴必須注入,即使是用不到時
2.set方法+<property>標籤
-
- 在類中,依賴通過setXXX方法賦值
- 配置檔案中,通過<property>標籤注入依賴:
屬性:
name: 注入資料的set方法名
value:注入的基本型別或String型別資料
ref:注入的bean型別資料。
<!-- set方法注入-->
<bean id="AccountService2" class="com.spring.two.service.AccountServiceImpl2">
<property name="name" value="neo"></property>
<property name="age" value="17"></property>
<property name="birthday" ref="birthday"></property>
</bean>
<bean id="birthday" class="java.util.Date"></bean>
優點:建立物件時,沒有明確的依賴限制,直接使用預設建構函式建立;
缺點:如果物件的某個依賴必須存在,通過set方式無法滿足此要求。