91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring?AOP底層原理及代理模式實例分析

發布時間:2022-05-30 13:50:49 來源:億速云 閱讀:156 作者:iii 欄目:開發技術

這篇文章主要介紹“Spring AOP底層原理及代理模式實例分析”,在日常操作中,相信很多人在Spring AOP底層原理及代理模式實例分析問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Spring AOP底層原理及代理模式實例分析”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

Spring AOP底層原理代理模式

一、什么是 AOP

AOP 就是面向切面編程,是 OOP(面向對象編程)的延續。

利用 AOP 可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序可用性,同時也提高了開發效率。

通俗一點說,不用修改原代碼,可以給原代碼增加新的功能。

二、AOP 底層原理

AOP 底層原理是使用動態代理。

那代理是什么?有動態代理,那是不是還有靜態代理?

1. 什么是代理?

就是為一個目標對象提供一個代理對象,并由代理對象控制對目標對象的引用。使用代理對象,是為了在不修改目標對象的基礎上,增強目標對象的業務邏輯。

比如目標對象 A,代理對象是 B。

  • 那么現在 B 對 A 進行引用,可以實現 A 有的功能。

  • 另外,B 還可以在自身進行一些新功能,最終不需要修改目標對象 A 。

而代理分為靜態代理和動態代理,區別是:

靜態代理有真實的代理類存在,就是我們會代碼中創建一個代理類,并在代理類的方法中調用目標對象的方法,以此來完成代理的工作。動態代理的代理類沒有在代碼中創建一個代理類,而是在運行時在JVM里面創建代理對象。

2. 什么是靜態代理

靜態代理是有實實在在的代理類存在,并且和目標類實現相同的接口。

比如,有一個轉賬業務,現在希望給它增加功能,使在轉賬之前確認轉賬人身份,以及轉賬之后通知收款人。

(1) 接口 AccountServiceDao :

package com.pingguo.spring5.dao;
public interface AccountServiceDao {
    // 主業務邏輯,轉賬
    void transfer();
}

(2) 接口 AccountServiceDao 的實現類:

package com.pingguo.spring5.dao;
public class AccountServiceImpl implements AccountServiceDao {
    @Override
    public void transfer() {
        System.out.println("調用dao層,完成轉賬主業務.");
    }
}

(3) 代理類 AccountProxy :

package com.pingguo.spring5.proxy;
import com.pingguo.spring5.dao.AccountServiceDao;
public class AccountProxy implements AccountServiceDao {
    // 目標對象
    private AccountServiceDao target;
    public AccountProxy(AccountServiceDao target) {
        this.target = target;
    }
    /**
     *  代理方法,實現對目標方法的增強
     */
    @Override
    public void transfer() {
        before();
        target.transfer();
        after();
    }
    /**
     *  增強的功能,轉賬之前使用
     */
    private void before() {
        System.out.println("對轉賬人身份進行驗證.");
    }
    /**
     *  增強的功能,轉賬之后使用
     */
    private void after() {
        System.out.println("轉賬完成,已通知收款人.");
    }
}

在代理類中:

  • 添加了添加了目標對象,并且有參構造方法里需要傳入目標對象。

  • 代理方法里,調用了目標對象里的轉賬方法 target.transfer()。

  • before() 和 after() 則是 2個增強的方法,分別作用于 target.transfer() 的前面和后面。

(4) 運行測試新建一個測試方法,運行看下結果:

@Test
    public void testProxy() {
        // 創建目標對象
        AccountServiceDao target = new AccountServiceImpl();
        // 創建代理對象
        AccountProxy proxy = new AccountProxy(target);
        proxy.transfer();
    }
  • 這里先創建了目標對象

  • 再創建代理對象,并且把目標對象傳入

  • 最后調用代理對象里的,被增強過的方法 transfer()。

結果:

對轉賬人身份進行驗證.
調用dao層,完成轉賬主業務.
轉賬完成,已通知收款人.
Process finished with exit code 0

優點:

  • 效率高,因為所有的類都是已經編寫完成的,使用的時候只需要取得代理對象并且執行即可。

  • 同時也可以實現對目標對象中指定的方法進行增強。

缺點:

  • 與目標類實現相同的接口代碼,冗余。

  • 如果接口發生改變,代理類中的方法也要修改。

  • 代理類服務于一種類型的對象,如果要服務多類型的對象,那么要為每種類型的對象都生成代理類。

3. 什么是動態代理

與靜態代理的硬編碼方式相比,動態代理支持運行時動態生成代理對象這種方式。換句話說,動態代理并不存在代理類,代理對象直接由代理生成工具動態生成。

優點:

  • 用很少的代碼對一個類的所有方法實現一樣的增強效果。

  • 在編碼時,代理邏輯與業務邏輯互相獨立,各不影響,減少侵入,降低耦合。

缺點:

相對于靜態代理,它不能增強其中的某一個方法。

對于動態代理,針對于是否存在接口的情況下,又分為 2 種:

  • 有接口的情況下,使用 JDK 動態代理。

  • 無接口的情況下,使用 CGLIB 動態代理。

使用 JDK 動態代理

使用 JDK 動態代理,創建的是接口實現類的代理對象,以此來實現功能增強。

現在不需要上面創建過的實際代理類了 。

接口,為了后面的一些知識點的說明,里面加個參數,轉賬的金額:

package com.pingguo.spring5.dao;
public interface AccountServiceDao {
    // 主業務邏輯,轉賬
    void transfer(int amount);
}

實現類:

package com.pingguo.spring5.dao;
public class AccountServiceImpl implements AccountServiceDao {
    @Override
    public void transfer(int amount) {
        System.out.println("調用dao層,完成轉賬主業務.金額:" + amount);
    }
}

在測試方法里,直接使用動態代理:

@Test
    public void testDynamicProxy() {
        // 創建目標對象
        AccountServiceDao target = new AccountServiceImpl();
        // 創建代理對象
        AccountServiceDao proxy = (AccountServiceDao) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),  // 目標類使用的類加載器
                target.getClass().getInterfaces(),  // 目標類實現的接口
                new InvocationHandler() {  // 調用處理器
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("對轉賬人身份進行驗證.");
                        Object res =  method.invoke(target, args);
                        System.out.println("轉賬完成,已通知收款人.");
                        return res;
                    }
                }
        );
        // 讓代理工作
        proxy.transfer(10000);
    }

運行結果:

對轉賬人身份進行驗證.
調用dao層,完成轉賬主業務.金額:10000
轉賬完成,已通知收款人.
Process finished with exit code 0

動態代理的過程:

  • 創建處理器 InvocationHandler實例。

  • 在調用目標對象時,會調用代理對象。

  • 代理對象去請求目標對象。invoke 方法就是調用目標對象的方法生成代理對象的過程。

  • 同時,在 invoke 方法中進行功能增強。

對于 invoke 中的 3 個參數,分別是:

  • Object proxy:代理對象,一般不會使用。

  • Method method:外面的代理對象調用的方法引用,這里引用的就是 transfer()

  • Object[] args:外面的代理對象調用的方法里面的參數,這里就是參數 amount。

使用 CGLIB 動態代理

CGLIB動態代理的原理是生成目標類的子類,這個子類對象就是代理對象,代理對象是被增強過的。

注意,不管有沒有接口都可以使用 CGLIB 動態代理, 而不是只有在無接口的情況下才能使用。

到此,關于“Spring AOP底層原理及代理模式實例分析”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

山西省| 德安县| 涟源市| 乐陵市| 武穴市| 车险| 洱源县| 五家渠市| 九寨沟县| 孟津县| 手机| 滨州市| 张掖市| 浙江省| 日喀则市| 旺苍县| 安新县| 安远县| 榕江县| 保靖县| 怀安县| 竹北市| 饶阳县| 临城县| 鹿泉市| 定兴县| 临潭县| 剑川县| 渝北区| 茂名市| 胶南市| 大田县| 和顺县| 弥渡县| 文成县| 房山区| 柳江县| 宝清县| 宾川县| 孝义市| 威信县|