1. 程式人生 > >spring(七)AOP,事務的隔離級別、傳播特性、配置

spring(七)AOP,事務的隔離級別、傳播特性、配置

AOP概念

Aop即面向切面程式設計、面向核心的業務方法程式設計,非核心交給spring去做,在模組中佔的比重非常少,主要體現是用在事務管理上。
1. 切面(Aspect):面向切面的“面”就是指的是本類,在類中面的組成就是方法的集合,JAVABean對應切面。
2. 連線點(JoinPoint)程式執行過程中的某個階段點。如某個方法呼叫,或者某個異常被丟擲。
3. 通知(Advice):處理邏輯,方法體中的業務邏輯,某個方法裡面的具體邏輯。
4. 切點(PointCut)一系列連線點的集合,它指明處理方式(Advice)將在何時被觸發,就是方法的集合。
結論:程式設計師只是關注最主要的業務邏輯或者方法。

為什麼需要AOP

面向切面程式設計能使程式設計師只是關注最主要的業務邏輯或者方法,其餘與業務無關的方法交個第三方面來做,騰出大量的時間使程式設計師關注最核心的業務方法,節省時間提高開發效率,是spring在面向物件的思想上新提出的一種程式設計思想。

事務的隔離級別

Isolation.READ_UNCOMMITTED:讀取未提交資料(會髒讀和不可重複讀)基本不用。
Isolation.READ_COMMITTED:讀已提交資料(不可重複讀和幻讀)oracle資料庫預設。
Isolation.REPETABLE_READ:可重複讀(幻讀)。Mysql和SQL server預設。
Isolation_SERIALIZABLE:序列化,最嚴格的級別,事務序列執行,資源消耗最大。
髒讀:一個事務讀取到另一個事務的未提交的資料,包含已提交的和未提交的,另一個事務回滾後資料又不見了。也就是說,比如事務A的未提交(還依然快取)的資料被事務B讀走,如果事務A失敗回滾,會導致事務B所讀取的的資料是錯誤的。
不可重複讀:在同一事務中多次讀取同一資料返回的結果有所不同,你在讀的時候其它人在修改。比如事務A中兩處讀取資料-total-的值。在第一讀的時候,total是100,然後事務B就把total的資料改成 200,事務A再讀一次,結果就發現,total竟然就變成200了,造成事務A資料混亂。相反,可重複多次讀取資料時能夠保證讀取資料一樣,也就是後續讀取不能讀取另一個事務已提交的更新資料。
幻讀:一個事務讀到另一個事務已提交的insert資料。這個和不可重複讀相似,也是同一個事務中多次讀不一致的問題。但是不可重複讀的不一致是因為他所要取的資料集被改變了(比如total的資料),但是幻讀所要讀的資料的不一致卻不是他所要讀的資料集改變,而是他的條件資料集改變。比如Select account.id where account.name=”ppgogo*”,第一次讀去了6個符合條件的id,第二次讀取的時候,由於事務b把一個帳號的名字由”dd”改成”ppgogo1”,結果取出來了7個數據。

事務傳播特性

在spring中基本的六種事務傳播(事務常量):
1. PROPAGATION_REQUIRED: 如果存在一個事務,則支援當前事務。如果沒有事務則開啟。
2. PROPAGATION_SUPPORTS: 如果存在一個事務,支援當前事務。如果沒有事務,則非事務的執行。
3. PROPAGATION_MANDATORY: 如果已經存在一個事務,支援當前事務。如果沒有一個活動的事務,則丟擲異常。
4. PROPAGATION_REQUIRES_NEW: 總是開啟一個新的事務。如果一個事務已經存在,則將這個存在的事務掛起。
5. PROPAGATION_NOT_SUPPORTED: 總是非事務地執行,並掛起任何存在的事務。
6. PROPAGATION_NEVER: 總是非事務地執行,如果存在一個活動事務,則丟擲異常。

spring配置事務

不配置也可進行操作,因為預設情況下是自動的處理事務,也可以手動配置。該配置是在ssm的基礎上進行的。

jar包

在SSMjar包的基礎上新增:spring-aop和spring-aspects的依賴,依賴包需要去2.0的spring原始碼包中找,其中aop的依賴是applicance,aspects的依賴是aspectjrt和aspectjweaver.

配置檔案

1.在配置檔案的頭部新增tx和aop的頭

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

2.配事務管理者

    <!-- 整合mybatis提供的事務管理者 -->
    <bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="mydataSource" />
    </bean>

3.配事務管理屬性

name:代表名稱符合該屬性的值的方法有該事務。
isolation:某個方法的事務隔離級別。
propagation:事務的傳播方式
rollback-for:有異常回滾值為異常類,前面加no代表有異常不回滾。
time-out:事務的過期時間,-1是永不過期,配30表示30毫秒不動就過期

<tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="delete*" propagation="REQUIRED"
                rollback-for="java.lang.Exception" />
            <tx:method name="save*" propagation="REQUIRED"
                rollback-for="java.lang.Exception" />
            <tx:method name="update*" propagation="REQUIRED"
                rollback-for="java.lang.Exception" />
            <tx:method name="find*" isolation="READ_COMMITTED"
                read-only="true" />
            <tx:method name="*" isolation="READ_COMMITTED" propagation="REQUIRED"
                read-only="true" />
        </tx:attributes>
    </tx:advice>

4.誰配置這個事務,將其配置到業務邏輯層。

aop:pointcut把事務的屬性注入到
advisor:通知
execution(* com.sxt.service..(..)):該表示式一般是固定的,第一個.表示這個包下的所有類,第二個.表示類中的所有方法,(..)表示方法的引數

    <aop:config>
        <aop:pointcut id="pc" expression="execution(* com.sxt.service.*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pc" />
    </aop:config>

註解方式

在業務邏輯層配。在類的頭部或者方法的頭部新增@Transactional註解,類頭配表示這是全域性事務對這個類底下的所有方法有效,
只能寫在public修飾的方法上,也可以在介面上寫,寫時是一樣的,但官方文件建議在類上寫,一般情況下增刪改在類上寫,查詢單獨配,當類頭部和方法的頭部都配置時,事務運用就近原則。
註解中的屬性,和配置檔案方式的配置是相同的,rollbackFor:既可以配置一個,也可以配多個異常。

package com.sxt.service;
import java.sql.SQLException;
import java.util.List;

import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.sxt.dao.DeptDaoMapper;
import com.sxt.entity.Dept;
@Service
@Transactional(propagation=Propagation.REQUIRED,rollbackFor={SQLException.class,Exception.class})
public class DeptService {
    @Resource(name="deptDaoMapper")
    private DeptDaoMapper deptDaoMapper;
    @Transactional(isolation=Isolation.READ_COMMITTED,readOnly=true,propagation=Propagation.REQUIRED)
    public List<Dept>findDept(){
        return deptDaoMapper.findDept();
    }
    @Transactional(propagation=Propagation.REQUIRED,rollbackFor={SQLException.class,Exception.class})
    public void save(){
    }
    @Transactional(propagation=Propagation.REQUIRED,rollbackForClassName={"SQLException","Exception"})
    public void delete(){
    }
    @Transactional(propagation=Propagation.REQUIRED,rollbackForClassName={"SQLException","Exception"})
    public void update(){
    }
}