最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring?AOP底層原理及代理模式

 更新時(shí)間:2022年05月30日 11:46:41   作者:把蘋果咬哭的測(cè)試筆記  
這篇文章主要為大家介紹了Spring?AOP底層原理及代理模式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Spring AOP底層原理代理模式

一、什么是 AOP

AOP 就是面向切面編程,是 OOP(面向?qū)ο缶幊?的延續(xù)。

利用 AOP 可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序可用性,同時(shí)也提高了開發(fā)效率。

通俗一點(diǎn)說(shuō),不用修改原代碼,可以給原代碼增加新的功能。

二、AOP 底層原理

AOP 底層原理是使用動(dòng)態(tài)代理。

那代理是什么?有動(dòng)態(tài)代理,那是不是還有靜態(tài)代理?

1. 什么是代理?

就是為一個(gè)目標(biāo)對(duì)象提供一個(gè)代理對(duì)象,并由代理對(duì)象控制對(duì)目標(biāo)對(duì)象的引用。使用代理對(duì)象,是為了在不修改目標(biāo)對(duì)象的基礎(chǔ)上,增強(qiáng)目標(biāo)對(duì)象的業(yè)務(wù)邏輯。

比如目標(biāo)對(duì)象 A,代理對(duì)象是 B。

  • 那么現(xiàn)在 B 對(duì) A 進(jìn)行引用,可以實(shí)現(xiàn) A 有的功能。
  • 另外,B 還可以在自身進(jìn)行一些新功能,最終不需要修改目標(biāo)對(duì)象 A 。

而代理分為靜態(tài)代理和動(dòng)態(tài)代理,區(qū)別是:

靜態(tài)代理有真實(shí)的代理類存在,就是我們會(huì)代碼中創(chuàng)建一個(gè)代理類,并在代理類的方法中調(diào)用目標(biāo)對(duì)象的方法,以此來(lái)完成代理的工作。動(dòng)態(tài)代理的代理類沒(méi)有在代碼中創(chuàng)建一個(gè)代理類,而是在運(yùn)行時(shí)在JVM里面創(chuàng)建代理對(duì)象。

2. 什么是靜態(tài)代理

靜態(tài)代理是有實(shí)實(shí)在在的代理類存在,并且和目標(biāo)類實(shí)現(xiàn)相同的接口。

比如,有一個(gè)轉(zhuǎn)賬業(yè)務(wù),現(xiàn)在希望給它增加功能,使在轉(zhuǎn)賬之前確認(rèn)轉(zhuǎn)賬人身份,以及轉(zhuǎn)賬之后通知收款人。

(1) 接口 AccountServiceDao :

package com.pingguo.spring5.dao;
public interface AccountServiceDao {
    // 主業(yè)務(wù)邏輯,轉(zhuǎn)賬
    void transfer();
}

(2) 接口 AccountServiceDao 的實(shí)現(xiàn)類:

package com.pingguo.spring5.dao;
public class AccountServiceImpl implements AccountServiceDao {
    @Override
    public void transfer() {
        System.out.println("調(diào)用dao層,完成轉(zhuǎn)賬主業(yè)務(wù).");
    }
}

(3) 代理類 AccountProxy :

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

在代理類中:

  • 添加了添加了目標(biāo)對(duì)象,并且有參構(gòu)造方法里需要傳入目標(biāo)對(duì)象。
  • 代理方法里,調(diào)用了目標(biāo)對(duì)象里的轉(zhuǎn)賬方法 target.transfer()。
  • before() 和 after() 則是 2個(gè)增強(qiáng)的方法,分別作用于 target.transfer() 的前面和后面。

(4) 運(yùn)行測(cè)試新建一個(gè)測(cè)試方法,運(yùn)行看下結(jié)果:

@Test
    public void testProxy() {
        // 創(chuàng)建目標(biāo)對(duì)象
        AccountServiceDao target = new AccountServiceImpl();
        // 創(chuàng)建代理對(duì)象
        AccountProxy proxy = new AccountProxy(target);
        proxy.transfer();
    }
  • 這里先創(chuàng)建了目標(biāo)對(duì)象
  • 再創(chuàng)建代理對(duì)象,并且把目標(biāo)對(duì)象傳入
  • 最后調(diào)用代理對(duì)象里的,被增強(qiáng)過(guò)的方法 transfer()。

結(jié)果:

對(duì)轉(zhuǎn)賬人身份進(jìn)行驗(yàn)證.
調(diào)用dao層,完成轉(zhuǎn)賬主業(yè)務(wù).
轉(zhuǎn)賬完成,已通知收款人.
Process finished with exit code 0

優(yōu)點(diǎn):

  • 效率高,因?yàn)樗械念惗际且呀?jīng)編寫完成的,使用的時(shí)候只需要取得代理對(duì)象并且執(zhí)行即可。
  • 同時(shí)也可以實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象中指定的方法進(jìn)行增強(qiáng)。

缺點(diǎn):

  • 與目標(biāo)類實(shí)現(xiàn)相同的接口代碼,冗余。
  • 如果接口發(fā)生改變,代理類中的方法也要修改。
  • 代理類服務(wù)于一種類型的對(duì)象,如果要服務(wù)多類型的對(duì)象,那么要為每種類型的對(duì)象都生成代理類。

3. 什么是動(dòng)態(tài)代理

與靜態(tài)代理的硬編碼方式相比,動(dòng)態(tài)代理支持運(yùn)行時(shí)動(dòng)態(tài)生成代理對(duì)象這種方式。換句話說(shuō),動(dòng)態(tài)代理并不存在代理類,代理對(duì)象直接由代理生成工具動(dòng)態(tài)生成。

優(yōu)點(diǎn):

  • 用很少的代碼對(duì)一個(gè)類的所有方法實(shí)現(xiàn)一樣的增強(qiáng)效果。
  • 在編碼時(shí),代理邏輯與業(yè)務(wù)邏輯互相獨(dú)立,各不影響,減少侵入,降低耦合。

缺點(diǎn):

相對(duì)于靜態(tài)代理,它不能增強(qiáng)其中的某一個(gè)方法。

對(duì)于動(dòng)態(tài)代理,針對(duì)于是否存在接口的情況下,又分為 2 種:

  • 有接口的情況下,使用 JDK 動(dòng)態(tài)代理。
  • 無(wú)接口的情況下,使用 CGLIB 動(dòng)態(tài)代理。

使用 JDK 動(dòng)態(tài)代理

使用 JDK 動(dòng)態(tài)代理,創(chuàng)建的是接口實(shí)現(xiàn)類的代理對(duì)象,以此來(lái)實(shí)現(xiàn)功能增強(qiáng)。

現(xiàn)在不需要上面創(chuàng)建過(guò)的實(shí)際代理類了 。

接口,為了后面的一些知識(shí)點(diǎn)的說(shuō)明,里面加個(gè)參數(shù),轉(zhuǎn)賬的金額:

package com.pingguo.spring5.dao;
public interface AccountServiceDao {
    // 主業(yè)務(wù)邏輯,轉(zhuǎn)賬
    void transfer(int amount);
}

實(shí)現(xiàn)類:

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

在測(cè)試方法里,直接使用動(dòng)態(tài)代理:

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

運(yùn)行結(jié)果:

對(duì)轉(zhuǎn)賬人身份進(jìn)行驗(yàn)證.
調(diào)用dao層,完成轉(zhuǎn)賬主業(yè)務(wù).金額:10000
轉(zhuǎn)賬完成,已通知收款人.
Process finished with exit code 0

動(dòng)態(tài)代理的過(guò)程:

  • 創(chuàng)建處理器 InvocationHandler實(shí)例。
  • 在調(diào)用目標(biāo)對(duì)象時(shí),會(huì)調(diào)用代理對(duì)象。
  • 代理對(duì)象去請(qǐng)求目標(biāo)對(duì)象。invoke 方法就是調(diào)用目標(biāo)對(duì)象的方法生成代理對(duì)象的過(guò)程。
  • 同時(shí),在 invoke 方法中進(jìn)行功能增強(qiáng)。

對(duì)于 invoke 中的 3 個(gè)參數(shù),分別是:

  • Object proxy:代理對(duì)象,一般不會(huì)使用。
  • Method method:外面的代理對(duì)象調(diào)用的方法引用,這里引用的就是 transfer()
  • Object[] args:外面的代理對(duì)象調(diào)用的方法里面的參數(shù),這里就是參數(shù) amount。

使用 CGLIB 動(dòng)態(tài)代理

CGLIB動(dòng)態(tài)代理的原理是生成目標(biāo)類的子類,這個(gè)子類對(duì)象就是代理對(duì)象,代理對(duì)象是被增強(qiáng)過(guò)的。

注意,不管有沒(méi)有接口都可以使用 CGLIB 動(dòng)態(tài)代理, 而不是只有在無(wú)接口的情況下才能使用。

示例就暫時(shí)不放了,因?yàn)槲冶镜丨h(huán)境問(wèn)題,有個(gè)報(bào)錯(cuò)始終未解決,后續(xù)再說(shuō),不影響繼續(xù)學(xué)習(xí) spring。

以上就是Spring AOP底層原理及代理模式的詳細(xì)內(nèi)容,更多關(guān)于Spring AOP底層原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • springboot通過(guò)spel結(jié)合aop實(shí)現(xiàn)動(dòng)態(tài)傳參的案例

    springboot通過(guò)spel結(jié)合aop實(shí)現(xiàn)動(dòng)態(tài)傳參的案例

    SpEl 是Spring框架中的一個(gè)利器,Spring通過(guò)SpEl能在運(yùn)行時(shí)構(gòu)建復(fù)雜表達(dá)式、存取對(duì)象屬性、對(duì)象方法調(diào)用等,今天通過(guò)本文給大家介紹springboot?spel結(jié)合aop實(shí)現(xiàn)動(dòng)態(tài)傳參,需要的朋友可以參考下
    2022-07-07
  • Mybatis中@Param注解的用法詳解

    Mybatis中@Param注解的用法詳解

    @Param注解的作用是給參數(shù)命名,參數(shù)命名后就能根據(jù)名字得到參數(shù)值,正確的將參數(shù)傳入sql語(yǔ)句中,下面這篇文章主要給大家介紹了關(guān)于Mybatis中@Param注解用法的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • IDEA .iml文件及.idea文件夾超詳細(xì)講解

    IDEA .iml文件及.idea文件夾超詳細(xì)講解

    iml文件是IntelliJ IDEA自己創(chuàng)建的模塊文件,用于java應(yīng)用開發(fā),存儲(chǔ)一些模塊相關(guān)的信息,比如一個(gè)Java組建,插件組建,Maven組建等,這篇文章主要介紹了IDEA .iml文件及.idea文件夾,需要的朋友可以參考下
    2023-09-09
  • Spring?Boot?Jwts?Token生成方法示例

    Spring?Boot?Jwts?Token生成方法示例

    這篇文章主要為大家介紹了Spring?Boot?Jwts?Token生成方法示例,非適合java初學(xué)者,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Java使用split截取字符串過(guò)程解析

    Java使用split截取字符串過(guò)程解析

    這篇文章主要介紹了Java使用split截取字符串過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Spring Batch 入門示例

    Spring Batch 入門示例

    本文將向您展示如何使用Spring Boot創(chuàng)建一個(gè)的Spring Batch的Hello World示例。對(duì)和我一樣入門的有一定的幫助,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Java微信掃碼登錄功能并實(shí)現(xiàn)認(rèn)證授權(quán)全過(guò)程

    Java微信掃碼登錄功能并實(shí)現(xiàn)認(rèn)證授權(quán)全過(guò)程

    這篇文章主要給大家介紹了關(guān)于Java微信掃碼登錄功能并實(shí)現(xiàn)認(rèn)證授權(quán)的相關(guān)資料,要在Java中實(shí)現(xiàn)微信掃碼登錄,您可以按照以下步驟進(jìn)行操作,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • Java的Jackson庫(kù)的使用及其樹模型的入門學(xué)習(xí)教程

    Java的Jackson庫(kù)的使用及其樹模型的入門學(xué)習(xí)教程

    這篇文章主要介紹了Java的Jackson庫(kù)的使用及其樹模型入門學(xué)習(xí)教程,Jackson庫(kù)通常被用來(lái)作Java對(duì)象和JSON的互相轉(zhuǎn)換,需要的朋友可以參考下
    2016-01-01
  • SpringBoot參數(shù)校驗(yàn)的一些實(shí)戰(zhàn)應(yīng)用

    SpringBoot參數(shù)校驗(yàn)的一些實(shí)戰(zhàn)應(yīng)用

    這篇文章主要給大家介紹了關(guān)于SpringBoot參數(shù)校驗(yàn)的一些實(shí)戰(zhàn)應(yīng)用,包括使用內(nèi)置的參數(shù)校驗(yàn)注解、嵌套對(duì)象校驗(yàn)、分組校驗(yàn)以及自定義校驗(yàn)注解,通過(guò)這些方法,可以有效地提高系統(tǒng)的穩(wěn)定性和安全性,需要的朋友可以參考下
    2024-11-11
  • IDEA啟動(dòng)tomcat控制臺(tái)中文亂碼問(wèn)題的解決方法(100%有效)

    IDEA啟動(dòng)tomcat控制臺(tái)中文亂碼問(wèn)題的解決方法(100%有效)

    很多人在idea中啟動(dòng)項(xiàng)目時(shí)會(huì)出現(xiàn)控制臺(tái)的中文亂碼,其實(shí)也無(wú)傷大雅,但是本人看著不舒服,下面這篇文章主要給大家介紹了關(guān)于IDEA啟動(dòng)tomcat控制臺(tái)中文亂碼問(wèn)題的解決方法,需要的朋友可以參考下
    2022-09-09

最新評(píng)論

灵山县| 敖汉旗| 通河县| 河间市| 铁岭县| 潜江市| 赣榆县| 郴州市| 岚皋县| 宝山区| 铜鼓县| 白水县| 拜泉县| 明光市| 新蔡县| 江油市| 马关县| 浦东新区| 威远县| 甘肃省| 麻江县| 文安县| 黔东| 尚义县| 九江市| 山东省| 资中县| 全州县| 沭阳县| 长乐市| 尼勒克县| 黔西县| 韶关市| 河南省| 平阳县| 游戏| 固安县| 松潘县| 隆回县| 南和县| 当雄县|