天天看點

Spring學習筆記(二)AOP1.AOP2.事務

Spring學習筆記(二)

  • 1.AOP
    • 1.1 AOP的基本概念
    • 1.2 AOP底層原理
    • 1.3 JDK動态代理
    • 1.4 術語
    • 1.5 準備工作
    • 1.6 基于AspectJ注解的方式
  • 2.事務
    • 2.1 事務概念

1.AOP

1.1 AOP的基本概念

  1. AOP:面向切面程式設計,利用AOP可以對業務邏輯的各個部分進行隔離,進而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。
  2. 通俗描述:不通過修改源代碼方式,在主幹功能中添加新的功能
  3. 場景引入
    Spring學習筆記(二)AOP1.AOP2.事務

1.2 AOP底層原理

  1. AOP底層使用動态代理

    (1)動态代理有兩種情況:

    ①有接口,使用JDK動态代理

    建立接口的代理對象,增強類的方法

    Spring學習筆記(二)AOP1.AOP2.事務
    ②沒有接口,使用CGLIB動态代理
    Spring學習筆記(二)AOP1.AOP2.事務
    ③差別:JDK建立實作類代理對象,CGLIB建立子類代理對象

1.3 JDK動态代理

  1. JDK的動态代理,使用Proxy類裡面的方法建立出代理對象
    Spring學習筆記(二)AOP1.AOP2.事務
    (1)調用newProxyInstance方法
    Spring學習筆記(二)AOP1.AOP2.事務

    第一個參數:ClassLoader類加載器

    第二個參數:增強方法所在的類所實作的接口,支援多個接口

    第三個參數:實作InvocationHandler接口,建立代理對象,寫增強的方法

  2. 代碼實作

    (1)建立接口,定義方法

public interface UserDao {
    public int add(int a,int b);
    public String update(String id);
}
           

(2)建立接口實作類,實作方法

public class UserDaoImpl implements UserDao {
    @Override
    public int add(int a, int b) {
        return a+b;
    }

    @Override
    public String update(String id) {
        return id;
    }
}
           

(3)使用Proxy類建立接口的代理對象

public class JDKProxy {
    public static void main(String[] args) {
        Class[] interfaces = {UserDao.class};
        UserDaoImpl userDao = new UserDaoImpl();
        UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new UserDaoProxy(userDao));
        int result = dao.add(1,2);
        System.out.println(result);
    }
}

//建立代理對象的代碼
class UserDaoProxy implements InvocationHandler{
    //建立哪個實作類的代理對象,需要傳入該實作類
    private Object obj;
    public UserDaoProxy(Object obj){
        this.obj = obj;
    }

    //增強的邏輯
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法之前
        System.out.println("增強方法之前被執行了..." + method.getName() + "傳遞的參數:" + Arrays.toString(args));

        //執行方法
        Object res = method.invoke(obj, args);

        //方法之後
        System.out.println("增強方法之後執行...");

        return res;
    }
           

①InvocationHandler接口,可以使用匿名内部類的方式傳遞,也可以編寫一個實作類傳遞。

②編寫InvocationHandler實作類,需要傳入需要增強的類。

③代理後會傳回一個新的實作類,需要接收。

1.4 術語

  1. 連接配接點:類裡面哪些方法可以被增強,這些方法稱為連接配接點
  2. 切入點:實際真正被增強的方法,成為切入點
  3. 通知(增強)

    (1)實際增強的邏輯部分成為通知(增強)

    (2)通知有多種類型:①前置通知 ②後置通知 ③環繞通知(在方法的前後都增強) ④異常通知(在發生異常時增強) ⑤最終通知 (類似finally,永遠會執行)

  4. 切面:把通知應用到切入點的過程,稱為切面,是一個動作

1.5 準備工作

  1. Spring架構基于AspectJ實作AOP操作

    AspectJ不是Spring組成部分,是獨立的AOP架構,一般把AspectJ和Spring架構一起使用,進行AOP操作

  2. 基于AspectJ實作AOP操作的兩種方式

    (1)基于xml配置檔案實作

    (2)基于注解方式實作

  3. AOP相關依賴檔案
    Spring學習筆記(二)AOP1.AOP2.事務
  4. 切入點表達式

    (1)切入點表達式:表示對類中的哪個方法進行增強

    (2)文法結構

    權限修飾符可省略

execution([權限修飾符][傳回類型][類全路徑][方法名稱](參數清單))

(3)示例

①對com.test.dao.BookDao類裡面的add方法進行增強

execution(* com.test.dao.BookDao.add(…))

②對com.test.dao.BookDao類中的所有方法進行增強

execution(* com.text.dao.BookDao.*(…))

③對com.test.dao包下的所有方法進行增強

execution(* com.test.dao.*(…))

1.6 基于AspectJ注解的方式

1、建立類,在類中定義方法

public class User {
    public void add(){
        System.out.println("add.......");
    }
}
           

2、建立增強類,編寫增強邏輯

(1)在增強類中建立方法,讓不同方法代表不同的通知類型

public class UserProxy {
    public void before(){
        System.out.println("before.......");
    }

}
           

3、進行aop相關配置

(1)在spring的配置檔案中,開啟注解掃描,開啟生成代理對象

<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <!-- 開啟注解掃描 -->
    <context:component-scan base-package="com.test.spring5"></context:component-scan>
    <!-- 開啟AspectJ生成代理對象 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
           

(2)使用注解建立被增強的類和增強類

(3)在增強類上添加注解@Aspect

4、配置不同類型的通知

(1)在增強類裡,作為通知方法上面添加通知類型注解,使用切入點表達式配置

@Component
@Aspect
public class UserProxy {
    @Before(value="execution(* com.test.spring5.User.add())")
    public void before(){
        System.out.println("before.......");
    }
    
    @Around(value="execution(* com.test.spring5.User.add())")
    public void around(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("環繞之前.......");
        proceedingJoinPoint.proceed();
        System.out.println("環繞之後.......");
    }
}
           

@Before 前置通知

@AfterReturning 後置通知 方法必須正确執行才會執行

@Around 環繞通知 參數ProceedingJoinPoint表示被增強的方法

@After 最終通知 無論方法是否正确運作都會執行,類似finally

@AfterThrowing 異常通知

優先級為Around→Before→After→AfterReturning→AfterThrowing

5、重用切入點的抽取

@PointCut(value="execution(* com.test.spring5.add())")
public void pointCut(){

}

@Before(value="pointCut()")
public void before(){
    System.out.println("before......");
}
           

@PointCut标簽抽取切入點,value寫标記的方法名

6、有多個增強類,對同一個方法進行增強,設定增強類優先級。

(1)在增強類上添加注解@Order(數字類型值),值越小優先級越高

2.事務

2.1 事務概念

  1. 什麼是事務

    (1)事務是資料庫操作最基本單元,邏輯上一組操作,要麼都成功,有一個失敗就全都失敗。

    (2)典型場景:銀行轉賬

  2. 事務四大特性(ACID)

    (1)原子性:要麼都成功,一個失敗都失敗

    (2)一緻性:事務送出前後的資料完整性和狀态保持一緻

    (3)隔離性:事務間是互相獨立的,不會互相影響

    (4)持久性:事務送出後表中資料真正發生了變化