天天看點

Spring5入門到實戰------9、AOP基本概念、底層原理、JDK動态代理實作

1、基本概念

  • (1)面向切面程式設計(方面),利用 AOP 可以對業務邏輯的各個部分進行隔離,進而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。
  • (2)通俗描述:不通過修改源代碼方式,在主幹功能裡面添加新功能
比如說、你完成了一個功能需求、後來産品經理在這個需求上增加一些新需求。你要麼修改源代碼(這個可能比較麻煩、耦合性也高)、這個時候就可以使用AOP切面程式設計、對原有的需求進行功能增強。橫切進去、就可以在不修改原先代碼的基礎上、完成新的需求(也友善後期維護、萬一産品經理說、這樣又不好呢。修改起來也容易、直接将切面拿走。)
  • (3)使用登入例子說明 AOP
  • Spring5入門到實戰------9、AOP基本概念、底層原理、JDK動态代理實作

2、底層原理

AOP 底層使用動态代理

有兩種情況動态代理

  • 第一種 有接口情況,使用 JDK 動态代理

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

Spring5入門到實戰------9、AOP基本概念、底層原理、JDK動态代理實作
  • 第二種 沒有接口情況,使用 CGLIB 動态代理

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

  • Spring5入門到實戰------9、AOP基本概念、底層原理、JDK動态代理實作

3、JDK動态代理實作

3.1 檢視對應Proxy方法使用

1、使用 JDK 動态代理,使用 Proxy 類裡面的方法建立代理對象

開胃小知識

Spring5入門到實戰------9、AOP基本概念、底層原理、JDK動态代理實作
Spring5入門到實戰------9、AOP基本概念、底層原理、JDK動态代理實作

3.2 方法詳解

(1)調用 newProxyInstance 方法

Spring5入門到實戰------9、AOP基本概念、底層原理、JDK動态代理實作

方法有三個參數:

第一參數,類加載器

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

第三參數,實作這個接口 InvocationHandler,建立代理對象,寫增強的部分

3.3 JDK動态代理代碼

3.3.1 建立接口,定義方法

PersonDao .java

/**
 * @author Lenovo
 * @version 1.0
 * @data 2022/10/19 22:37
 */
public interface PersonDao {
    public int add(int a,int b);

    public void update(int a);
}      

3.3.2 建立接口實作類,實作方法

PersonDaoImpl.java

/**
 * @author Lenovo
 * @version 1.0
 * @data 2022/10/19 22:39
 */
public class PersonDaoImpl implements PersonDao {
    @Override
    public int add(int a, int b) {
        System.out.println("執行了add方法");
        return a+b;
    }

    @Override
    public void update(int a) {
        System.out.println(a);
    }
}
      

3.3.3 使用 Proxy 類建立接口代理對象

/**
 * @author Lenovo
 * @version 1.0
 * @data 2022/10/19 22:40
 */
public class JdkProxy {
    public static void main(String[] args) {
        //建立接口實作類代理對象
        Class[] interfaces = {PersonDao.class};
//        Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), interfaces,
//                new InvocationHandler() {
//                    @Override
//                    public Object invoke(Object proxy, Method method, Object[] args)
//                            throws
//                            Throwable {
//                        return null;
//                    }
//                });
        PersonDaoImpl personDao = new PersonDaoImpl();
        PersonDao dao = (PersonDao) Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), interfaces, new PersonDaoProxy(personDao));
        int rs = dao.add(4, 5);
        System.out.println("result:" + rs);

    }
}

/**
 * 代理對象代碼
 */
class PersonDaoProxy implements InvocationHandler {
    /**
     * 1 把建立的是誰的代理對象,把誰傳遞過來
     *  有參數構造傳遞
     */
    private Object obj;

    public PersonDaoProxy(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 rs = method.invoke(obj, args);
        //方法之後
        System.out.println("方法執行之後:" + obj);
        return rs;
    }
}      
Spring5入門到實戰------9、AOP基本概念、底層原理、JDK動态代理實作

3.3.4 測試結果

4、後語