Spring
三大重點 : IoC/DI、AOP、整合其他框架(例如 : Hibernate、MyBatis)
分為很多個模組,有需要某功能再把.jar 加進來
IoC/DI 機制
IoC 託管
- 被託管的物件稱為 Bean 元件
- 將 Java 中的物件託給 Spring 管理
- 物件的 實例化、初始化、存活範圍、銷毀,皆由 Spring 控制
- 官方建議將物件抽介面(抽象化)
控制反轉到底在做甚麼?
簡單來說,本來是靠我們 new 兂的物件來做事情,現在這件事交由 Spring 處理,我們只要利用 Spring 提供的容器型態就可以取得 Spring 管理的物件。
Spring 提供很多 IoC 容器型態供使用,共同父型態為 BeanFactory,有一重要方法 getBean()以取得 Bean 元件。
通常在寫 web 時將 ServletContext 轉換成 Java 可用的 ApplicationContext 物件。
1 | //以在web環境前提下使用WebApplicationContext |
要先託管好,依賴注入才拿的到東西。。。
不然你就會一直看到 this.dao is null。。。
DI 依賴注入
- 如果要使用某 Bean 元件,透過 DI 來取得
- DI 使用父型態(即介面),減少相依性
組態設定
這裡以 Java+annotation 示範。。。
xml 太麻煩ㄌ。。。
- 記得掃描(Scan)套件(指定 Bean 元件位置)
- 找到後會實例化並接管 Bean
- 若 此 Bean 元件 ⼜依賴 其他 Bean 元件,亦會同時注⼊(DI)依賴的 Bean 元件
- 為了區分語意不使用@Component 而是帶有語意的@Repository、@Service
設定託管 :
1 |
|
設定注入 @Autowired :
1 |
|
建立核心組態類別 :
1 |
|
在 web.xml 中指定 IoC/DI 組態 :
ContextLoaderListener 類別
- 由 Spring 定義,為 Servlet API 中 ServletContextListener 介⾯的⼦實作類別
- 註冊此監聽器,並設定特定參數值,即可指定
Spring 的 組態檔/組態類別
參數 :
- contextConfigLocation : String type,用來指定 Spring 組態檔或是組態類別
- contextClass : Class<?> type,用來指定 IoC 容器型態,default 為配合 xml based 的 XmlWebApplicationContext 類別,如要使用 Java based 須額外設定 AnnotationConfigWebApplicationContext 類別
1 |
|
1 |
|
Spring 中 JNDI 的支援
- Spring 提供 JndiObjectFactoryBean 類別,以對應 Web 容器提供的 JNDI
- 會接管 託 JNDI 管理的物件(像是 DataSource)
- 接著再設定成 Bean 元件,即可在 Spring IoC/DI 機制使用 JNDI 中的物件
重要屬性 :
- resourceRef : boolean 型態,預設為 false。若設為 true,則 jndiName 屬性值可省去 “java:comp/env/“
- jndiName : String 型態,託管在 JNDI 的物件之名稱
1 |
|
jdbc/javaFramework : 對應 context.xml 中,
標籤的 name 屬性之值
afterPropertiesSet() : 使⽤ Java 組態時,須⼿動呼叫此⽅法
Spring 中 Hibernate 的支援
Hibernate 組態設定皆在 tag
<session-factory>中,可以說 SessionFactory 物件是 Hibernate 最核心的物件
Spring 為 Hibernate 提供以下支援
- XML Based : 使⽤ LocalSessionFactoryBean
- Java Based : 使⽤ LocalSessionFactoryBuilder
Java Based :
在之前建立的核心組態 class AppConfig 託管 LocalSessionFactoryBuilder。
基本上就是將 hibernate.cfg.xml 中的設定,搬移⾄核⼼組態類別中
與 hibernate.cfg.xml 不同的是
- Session 環境管理 : 使⽤ Spring 提供的SpringSessionContext 類別
- 註冊實體類別: 可以使⽤ scanPackages()⽅法,指定欲掃描的套件,與 Hibernate 一樣都要記得 mapping entity
1 |
|
HibernateFilter支援
在 Hibernate 中可以使用 Filter 來做交易控制
Spring 有提供 OpenSessionInViewFilter 可以做使用
在 web.xml 中註冊 :
1 |
|
在Spring中注入Session物件
在核心組態設定時已經託管好了 SessionFactory 物件,我們的 DAO 即可注入此物件直接取的 Session 物件
不需要再寫像
1 | Session session = getSession(); |
這樣的程式,但有另一個問題,Session 物件非執行續安全(Thread-Safe),直接使用 Spring 來注入會有多個執行續共用同一 Session 物件的問題,因此使用@PersistenceContext 解決問題
@PersistenceContext 為 JPA 提供之 API
- 用來注入 EntityManager 型態的物件,⽽ Hibernate 的 Session 型態,即為
EntityManager 的⼦代 - 在底層仍是注入 SessionFactory 物件,但會自動呼叫
openSession()/getCurrentSession(),以取得 Session 物件 - 效能上並不會提升,僅用來簡化程式碼
1 |
|
Spring - AOP
AOP 為(Aspect-oriented programming),譯為切面導向程式設計
在 Spring in action 4 中有一段文字是這樣描述的 :
AOP 允許你把遍布應用各處的功能分離出來行程可重複使用的組件。
概念有點像是,你沒有改這段程式碼,但這段程式碼被改變了。
實際開發情境中,卻⼜常將系統功能相關程式,穿插撰寫在商業邏輯相關程式中,且重複出現。
這樣的程式,讓本⾝就繁雜的商業邏輯相關程式,更加複雜,且不易維護。
通常會用在 :
- 系統功能 : 純軟體技術形成的功能,EX.交易控制、⽇誌(Log)、資安處理
- 商業邏輯 : 依專案需求形成的功能,EX.會員註冊、會員登⼊、會員登出、會員資料編輯
這個概念比較抽象,但就我自己的理解和老師的說明,@Transcational 的這個 annotation 有點像這個概念,詳見講義,不再此多做說明。
交易控制
- 交易控制(Transaction Control),⼜稱交易管理(Transaction Management)
- 意指控制資料庫的交易
- 順利執行 -> commit
- 發生執行例外 -> rollback
重要型態
套件 org.springframework.transaction
PlatformTransactionManager
- 交易管理器,是 Spring-交易控制最核⼼的型態
- 常用子實作類別
- DataSourceTransactionManager : 配合 JDBC 使⽤
- JpaTransactionManager : 配合 JPA 使⽤
- HibernateTransactionManager : 配合 Hibernate 使⽤
TransactionDefinition
- 交易定義,交易的細節設定。相關設定值由@Transactional 設定
- 傳播⾏為(Propagation behavior) : 交易 何時開始、何時結束、是否需要交易
- 隔離等級(Isolation level) : 當前交易,與其他交易的隔離程度
- 逾時(Timeout) :
- 針對較耗時的交易,可在逾時時自動 rollback
- 須配合傳播⾏為 PROPAGATION_REQUIRED 或 PROPAGATION_REQUIRES_NEW 使⽤
- 唯讀(Read-only) :
- 若交易中只執⾏了 SQL 的 select 敘述,通常資料庫端可做⼀些優化
- 須配合傳播⾏為 PROPAGATION_REQUIRED 或 PROPAGATION_REQUIRES_NEW 使⽤
TransactionStatus
- 交易狀態,除了部分取代 JDBC API 中的 Connection 型態外,亦可⽤來取得交易相關資訊
- 可設定 新建儲存點、釋放儲存點、還原⾄儲存點、設定交易只能還原 等控制
- 可取得 有儲存點否、完成否、為新建否、只能還原(rollback)否 等資訊
@Transcational
- 用以標註需要交易控制的⽅法。亦可加註在型態上,表⽰其內所有⽅法皆需交易控制
- 交易管理器會使⽤ Spring-AOP 機制,連接有標註此 Annotation 的⽅法,進⽽做交易控制
- 預設狀況下,發⽣ RuntimeException 例外時,才會 Rollback
1 |
|
MVC 架構中,@Transcational 應放在 service 中欲受交易控制的 method 上。
以上即完成 Spring 基礎轉換,後續還可將 DAO、VO 抽換成 Spring Data JPA/MyBatis、整體抽換成 Spring MVC、Spring Boot。
詳見後續筆記。




