溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Spring中AOP概念與兩種動(dòng)態(tài)代理模式原理是什么

發(fā)布時(shí)間:2021-10-25 09:07:34 來(lái)源:億速云 閱讀:120 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容介紹了“Spring中AOP概念與兩種動(dòng)態(tài)代理模式原理是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

    1.概念

    1.AOP技術(shù)簡(jiǎn)介

    AOP 為Aspect Oriented Programming 的縮寫,意思為面向切面編程,是通過(guò)預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。

    AOP 是 OOP 的延續(xù),是軟件開發(fā)中的一個(gè)熱點(diǎn),也是Spring框架中的一個(gè)重要內(nèi)容,是函數(shù)式編程的一種衍生范型。利用AOP可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開發(fā)的效率。

    2.AOP的優(yōu)勢(shì)

    作用:在程序運(yùn)行期間,在不修改源碼的情況下對(duì)方法進(jìn)行功能增強(qiáng)優(yōu)勢(shì):減少重復(fù)代碼,提高開發(fā)效率,并且便于維護(hù)

    3.Spring AOP術(shù)語(yǔ)

    Spring 的 AOP 實(shí)現(xiàn)底層就是對(duì)上面的動(dòng)態(tài)代理的代碼進(jìn)行了封裝,封裝后我們只需要對(duì)需要關(guān)注的部分進(jìn)行代碼編寫,并通過(guò)配置的方式完成指定目標(biāo)的方法增強(qiáng)。在正式講解 AOP 的操作之前,我們必須理解 AOP 的相關(guān)術(shù)語(yǔ),常用的術(shù)語(yǔ)如下:

    Target(目標(biāo)對(duì)象):代理的目標(biāo)對(duì)象Proxy (代理):一個(gè)類被 AOP 織入增強(qiáng)后,就產(chǎn)生一個(gè)結(jié)果代理類Joinpoint(連接點(diǎn)):所謂連接點(diǎn)是指那些被攔截到的點(diǎn)。在spring中,這些點(diǎn)指的是方法,因?yàn)閟pring只支持方法類型的連接點(diǎn).(可能被增強(qiáng)的方法)Pointcut(切入點(diǎn)):所謂切入點(diǎn)是指我們要對(duì)哪些 Joinpoint 進(jìn)行攔截的定義(被增強(qiáng)的方法)Advice(通知/ 增強(qiáng)):所謂通知是指攔截到 Joinpoint 之后所要做的事情就是通知(對(duì)目標(biāo)對(duì)象增強(qiáng)的方法)Aspect(切面):是切入點(diǎn)和通知(引介)的結(jié)合(目標(biāo)方法+增強(qiáng)=切面)Weaving(織入):是指把增強(qiáng)應(yīng)用到目標(biāo)對(duì)象來(lái)創(chuàng)建新的代理對(duì)象的過(guò)程。 spring采用動(dòng)態(tài)代理織入,而AspectJ采用編譯期織入和類裝載期織入.(一個(gè)動(dòng)作,切點(diǎn)和通知結(jié)合的過(guò)程=織入)

    4.AOP 開發(fā)明確的事項(xiàng)

    需要編寫的內(nèi)容 編寫核心業(yè)務(wù)代碼(目標(biāo)類的目標(biāo)方法)編寫切面類,切面類中有通知(增強(qiáng)功能方法)在配置文件中,配置織入關(guān)系,即將哪些通知與哪些連接點(diǎn)進(jìn)行結(jié)合 AOP 技術(shù)實(shí)現(xiàn)的內(nèi)容 Spring 框架監(jiān)控切入點(diǎn)方法的執(zhí)行。一旦監(jiān)控到切入點(diǎn)方法被運(yùn)行,使用代理機(jī)制,動(dòng)態(tài)創(chuàng)建目標(biāo)對(duì)象的代理對(duì)象,根據(jù)通知類別,在代理對(duì)象的對(duì)應(yīng)位置,將通知對(duì)應(yīng)的功能織入,完成完整的代碼邏輯運(yùn)行。 AOP 底層使用哪種代理方式 在 spring 中,框架會(huì)根據(jù)目標(biāo)類是否實(shí)現(xiàn)了接口來(lái)決定采用哪種動(dòng)態(tài)代理的方式。

     2.AOP底層實(shí)現(xiàn)

    實(shí)際上, AOP 的底層是通過(guò) Spring 提供的的動(dòng)態(tài)代理技術(shù)實(shí)現(xiàn)的。在運(yùn)行期間, Spring通過(guò)動(dòng)態(tài)代理技術(shù)動(dòng)態(tài)的生成代理對(duì)象,代理對(duì)象方法執(zhí)行時(shí)進(jìn)行增強(qiáng)功能的介入,在去調(diào)用目標(biāo)對(duì)象的方法,從而完成功能的增強(qiáng)。

    1.AOP 的動(dòng)態(tài)代理技術(shù):

    常用的動(dòng)態(tài)代理技術(shù)

    • JDK 代理 : 基于接口的動(dòng)態(tài)代理技術(shù)

    • cglib 代理:基于父類的動(dòng)態(tài)代理技術(shù)

    Spring中AOP概念與兩種動(dòng)態(tài)代理模式原理是什么

    2.基于jdk的動(dòng)態(tài)代理代碼

    //---------接口1------------
    package com.itspring.proxy.jdk;
    
    public interface TargetInterface1 {
        void save();
    }
    
    
    //---------接口2------------
    package com.itspring.proxy.jdk;
    
    public interface TargetInterface2 {
        void update();
    }
    
    
    //---------接口1,接口2實(shí)現(xiàn)類(目標(biāo)類)------------
    package com.itspring.proxy.jdk;
    
    //目標(biāo)類(被增強(qiáng)的類)
    public class Target implements TargetInterface1 ,TargetInterface2{
        public void save() {
            System.out.println("save running...");
        }
    
        public void update() {
            System.out.println("update running...");
        }
    }
    //---------通知類(方法增強(qiáng)類)------------
    package com.itspring.proxy.jdk;
    
    //通知類(增強(qiáng)類)
    public class Advice {
    
        public void before() {
            System.out.println("前置增強(qiáng)...");
        }
    
        public void afterRunning() {
            System.out.println("后置增強(qiáng)...");
        }
    }
    //---------測(cè)試代碼------------
    package com.itspring.proxy.jdk;
    
    import org.junit.Test;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyTest {
    
        @Test
        public void test1() {
    
            final Target target = new Target();
    
            final Advice advice = new Advice();
    
            //返回值就是動(dòng)態(tài)生成的代理對(duì)象
            TargetInterface1 proxy1 = (TargetInterface1) Proxy.newProxyInstance(
                    target.getClass().getClassLoader(),  //目標(biāo)類的類加載器
                    target.getClass().getInterfaces(),  //目標(biāo)類實(shí)現(xiàn)的接口(可能有多個(gè))
                    new InvocationHandler() {
                        //調(diào)用代理對(duì)象的任何方法,實(shí)質(zhì)上都是調(diào)用invoke方法
                        public Object invoke(Object proxy,  //代理對(duì)象
                                             Method method,  //目標(biāo)方法對(duì)象
                                             Object[] args  //目標(biāo)方法的參數(shù)
                        ) throws Throwable {
                            System.out.println("正在執(zhí)行的方法:" + method.getName());
                            advice.before();  //前置增強(qiáng)
                            Object invoke = method.invoke(target, args);  //執(zhí)行目標(biāo)方法
                            advice.afterRunning();  //后置增強(qiáng)
                            return invoke;
                        }
                    }
            );
    
            proxy1.save();
    
            //返回值就是動(dòng)態(tài)生成的代理對(duì)象
            TargetInterface2 proxy2 = (TargetInterface2) Proxy.newProxyInstance(
                    target.getClass().getClassLoader(),  //目標(biāo)類的類加載器
                    target.getClass().getInterfaces(),  //目標(biāo)類實(shí)現(xiàn)的接口(可能有多個(gè))
                    new InvocationHandler() {
                        //調(diào)用代理對(duì)象的任何方法,實(shí)質(zhì)上都是調(diào)用invoke方法
                        public Object invoke(Object proxy,  //代理對(duì)象
                                             Method method,  //目標(biāo)方法對(duì)象
                                             Object[] args  //目標(biāo)方法的參數(shù)
                        ) throws Throwable {
                            System.out.println("正在執(zhí)行的方法:" + method.getName());
                            advice.before();
                            Object invoke = method.invoke(target, args);  //執(zhí)行目標(biāo)方法
                            advice.afterRunning();
                            return invoke;
                        }
                    }
            );
    
            proxy2.update();
        }
    }

    Spring中AOP概念與兩種動(dòng)態(tài)代理模式原理是什么

    3.基于cglib的動(dòng)態(tài)代理代碼

    cglib是第三方的庫(kù),spring集成了cglib.

    Spring中AOP概念與兩種動(dòng)態(tài)代理模式原理是什么

    Spring中AOP概念與兩種動(dòng)態(tài)代理模式原理是什么

    //---------目標(biāo)類-------------
    package com.itspring.proxy.cglib;
    
    import com.itspring.proxy.jdk.TargetInterface1;
    import com.itspring.proxy.jdk.TargetInterface2;
    
    //目標(biāo)類(被增強(qiáng)的類)
    public class Target {
        public void save() {
            System.out.println("save running...");
        }
    
        public void update() {
            System.out.println("update running...");
        }
    }
    //---------通知類(增強(qiáng)類)-------------
    package com.itspring.proxy.cglib;
    
    //通知類(增強(qiáng)類)
    public class Advice {
    
        public void before() {
            System.out.println("前置增強(qiáng)...");
        }
    
        public void afterRunning() {
            System.out.println("后置增強(qiáng)...");
        }
    }
    //---------測(cè)試代碼-------------
    package com.itspring.proxy.cglib;
    
    import com.itspring.proxy.jdk.TargetInterface1;
    import com.itspring.proxy.jdk.TargetInterface2;
    import org.junit.Test;
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyTest {
    
        @Test
        public void test1() {
            //目標(biāo)對(duì)象
            final Target target = new Target();
    
            //增強(qiáng)對(duì)象
            final Advice advice = new Advice();
    
            //基于cglib生成動(dòng)態(tài)代理對(duì)象
            //1.創(chuàng)建增強(qiáng)器
            Enhancer enhancer = new Enhancer();
            //2.創(chuàng)建父類
            enhancer.setSuperclass(Target.class);
            //3.設(shè)置回調(diào)
            enhancer.setCallback(new MethodInterceptor() {
                public Object intercept(Object proxy,  //代理對(duì)象
                                        Method method,  //目標(biāo)方法
                                        Object[] objects,  //目標(biāo)方法的參數(shù)
                                        MethodProxy methodProxy)  //目標(biāo)方法的代理
                        throws Throwable {
                    //前置增強(qiáng)
                    advice.before();
                    //目標(biāo)方法
                    Object invoke = method.invoke(target, objects);
                    //后置增強(qiáng)
                    advice.afterRunning();
                    return invoke;
                }
            });
            //4.生成代理對(duì)象
            Target target1 = (Target) enhancer.create();
            //5.測(cè)試
            target1.save();
            target1.update();
    
        }
    }

    Spring中AOP概念與兩種動(dòng)態(tài)代理模式原理是什么

    “Spring中AOP概念與兩種動(dòng)態(tài)代理模式原理是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI