欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring細(xì)數(shù)兩種代理模式之靜態(tài)代理和動態(tài)代理概念及使用

 更新時(shí)間:2023年02月27日 09:52:27   作者:Java Fans  
代理是一種設(shè)計(jì)模式,提供了對目標(biāo)對象另外的訪問方式,即通過代理對象訪問目標(biāo)對象??梢圆恍薷哪繕?biāo)對象,對目標(biāo)對象功能進(jìn)行拓展。在我們學(xué)習(xí)Spring的時(shí)候就會發(fā)現(xiàn),AOP(面向切面編程)的底層就是代理

代理模式

在學(xué)習(xí) AOP 之前,我們先來了解下代理模式, 代理模式分為靜態(tài)代理以及動態(tài)代理,屬于23中設(shè)計(jì)模式之一。 AOP 的底層機(jī)制就是動態(tài)代理。

作用:

通過代理類為原始類增加額外的功能

1、靜態(tài)代理

1)案例展示

【1】定義一個(gè) Teacher 接口,接口中定義兩個(gè)方法:teachOnLine 和 teachOffLine。

package cn.gc.spring03.interfce;
public interface Teacher {
    String teachOnLine(String course);
    String teachOffLine(String course);
}

【2】定義一個(gè)實(shí)現(xiàn) Teacher 接口的 TeacherA 實(shí)現(xiàn)類,代碼如下:

package cn.gc.spring03.interfce.impl;
import cn.gc.spring03.interfce.Teacher;
public class TeacherA implements Teacher {
    @Override
    public String teachOnLine(String course) {
        System.out.println("開始"+course+"課程線上教學(xué)");
        return course+"課程線上教學(xué)";
    }
    @Override
    public String teachOffLine(String course) {
        System.out.println("開始"+course+"課程線下教學(xué)");
        return course+"課程線下教學(xué)";
    }
}

【3】現(xiàn)在我們要在兩個(gè)方法中的 開始課程教學(xué) 的前后添加上下課鈴聲的功能,此時(shí)我們再定義一個(gè)實(shí)現(xiàn) Teacher 接口的靜態(tài)代理類 TeacherAStaticProxy,代碼如下:

package cn.gc.spring03.proxy;
import cn.gc.spring03.interfce.Teacher;
import cn.gc.spring03.interfce.impl.TeacherA;
public class TeacherAStaticProxy implements Teacher {
    TeacherA teacherA=new TeacherA();
    @Override
    public String teachOnLine(String course) {
        System.out.println(course+"課程上課時(shí)間到了");
        String s = teacherA.teachOnLine(course);
        System.out.println(course+"課程下課時(shí)間到了");
        return s;
    }
    @Override
    public String teachOffLine(String course) {
        System.out.println(course+"課程上課時(shí)間到了");
        String s = teacherA.teachOffLine(course);
        System.out.println(course+"課程下課時(shí)間到了");
        return s;
    }
}

【4】運(yùn)行效果如下

2)靜態(tài)代理優(yōu)缺點(diǎn)

(1)優(yōu)點(diǎn) :在不修改目標(biāo)對象的功能前提下,能通過代理對象對目標(biāo)功能擴(kuò)展;可以使得真實(shí)角色更加純粹,不再去關(guān)注一些公共的事情;公共的業(yè)務(wù)由代理來完成,實(shí)現(xiàn)了業(yè)務(wù)的分工。

(2)缺點(diǎn) :因?yàn)榇韺ο笮枰c目標(biāo)對象實(shí)現(xiàn)一樣的接口,所以會很多代理類 ,一旦接口增加方法,目標(biāo)對象與代理對象都要維護(hù),工作量變大,開發(fā)效率降低。

3)開發(fā)代理對象的原則

  • 代理對象和目標(biāo)對象實(shí)現(xiàn)相同的接口
  • 代理對象依賴于目標(biāo)對象

2、動態(tài)代理

在不改變原來的代碼的情況下,實(shí)現(xiàn)了對原有功能的增強(qiáng),這是 AOP 中最核心的思想。

AOP:縱向開發(fā),橫向開發(fā)

1)簡介

動態(tài)代理的角色和靜態(tài)代理的一樣。但是動態(tài)代理的代理類是動態(tài)生成的,而靜態(tài)代理的代理類是提前寫好的。

動態(tài)代理分為兩類,一類是基于接口動態(tài)代理(JDK),一類是基于類的動態(tài)代理(CGLib)。

2)基于接口動態(tài)代理(JDK)

程序運(yùn)行的過程中,通過 JDK 提供代理技術(shù)動態(tài)的為某個(gè)類產(chǎn)生動態(tài)代理對象的過程。

開發(fā)代理對象的原則:

  • 代理對象,不需要實(shí)現(xiàn)接口,但是目標(biāo)對象要實(shí)現(xiàn)接口,否則不能用JDK動態(tài)代理。
  • 代理對象的生成,是利用JDK的API,動態(tài)的在內(nèi)存中構(gòu)建代理對象。
  • 動態(tài)代理也叫做 :JDK代理、接口代理。

JDK 的動態(tài)代理需要了解兩個(gè)類:

核心 : InvocationHandler (調(diào)用處理程序) 和 Proxy (代理)

實(shí)現(xiàn)步驟:在上面案例的基礎(chǔ)上實(shí)現(xiàn)。

創(chuàng)建一個(gè)基于 JDK 的代理工具類 DynamicProxy 類:

package cn.gc.spring03.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/*
 * 基于JDK的代理工具類
 */
public class DynamicProxy {
    //被代理對象
    private Object target;
    public DynamicProxy(Object obj) {
        this.target = obj;
    }
    //生成代理對象
    public Object getProxy() {
        //獲取類加載器
        ClassLoader classLoader = target.getClass().getClassLoader();
        //獲取被代理對象實(shí)現(xiàn)的所有接口
        Class<?>[] interfaces = target.getClass().getInterfaces();
        //增強(qiáng)功能代碼編寫的位置
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 增強(qiáng)的功能
                System.out.println(args[0] + "課程上課時(shí)間到了");
                // 通過反射執(zhí)行目標(biāo)方法
                Object invoke = method.invoke(target, args);
                // 增強(qiáng)的功能
                System.out.println(args[0] + "課程下課時(shí)間到了");
                return invoke;
            }
        };
        Object o = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        return o;
    }
}

測試:

    @Test
    public void test02() {
        Teacher teacher  = new TeacherA();
        DynamicProxy dynamicProxy = new DynamicProxy(teacher);
        Teacher teacherProxy = (Teacher) dynamicProxy.getProxy();
        teacherProxy.teachOnLine("Java");
        System.out.println("______________________");
        teacherProxy.teachOnLine("C++");
    }

運(yùn)行效果:

3)基于類的動態(tài)代理(CGLib)

開發(fā)代理對象的原則:

  • 代理對象無需和原始類對象實(shí)現(xiàn)相同的接口
  • 代理對象和原始類對象要存在父子類關(guān)系

CGLib 的動態(tài)代理需要了解兩個(gè)類:

  • 核心 : Enhancer 和 MethodInterceptor

實(shí)現(xiàn)步驟

創(chuàng)建一個(gè) Aoo 類:

package cn.gc.spring03.interfce.impl;
public class Aoo {
    public String test01(String info){
        System.out.println("Aoo中的test01方法被調(diào)用。");
        return info;
    }
}

創(chuàng)建一個(gè)基于 CGLib 的代理工具類 CglibProxy 類:

package cn.gc.spring03.proxy;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxy {
    private Object target;
    public CglibProxy(Object obj){
        this.target=obj;
    }
    public Object getProxy(){
        Enhancer enhancer=new Enhancer();
        //設(shè)置類加載器
        enhancer.setClassLoader(CglibProxy.class.getClassLoader());
        //設(shè)置被代理對象
        enhancer.setSuperclass(target.getClass());
        //增強(qiáng)功能代碼編寫的位置
        MethodInterceptor methodInterceptor=new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("-------------cglib log--------------");
                Object invoke = method.invoke(target, objects);
                System.out.println("-------------cglib log--------------");
                return invoke;
            }
        };
        enhancer.setCallback(methodInterceptor);
        //代理對象
        Object o = enhancer.create();
        return o;
    }
}

測試:

    @Test
    public void test03() {
        Aoo aoo=new Aoo();
        CglibProxy cglibProxy = new CglibProxy(aoo);
        Aoo proxy = (Aoo) cglibProxy.getProxy();
        String info = proxy.test01("java");
        System.out.println("info = " + info);
    }

運(yùn)行效果:

4)動態(tài)代理的優(yōu)勢

  • 可以使得真實(shí)角色更加純粹,不再去關(guān)注一些公共的事情。
  • 公共的業(yè)務(wù)由代理來完成,實(shí)現(xiàn)了業(yè)務(wù)的分工。
  • 公共業(yè)務(wù)發(fā)生擴(kuò)展時(shí)變得更加集中和方便。
  • 一個(gè)動態(tài)代理,一般代理某一類業(yè)務(wù)。
  • 一個(gè)動態(tài)代理可以代理多個(gè)類,代理的是接口。

到此這篇關(guān)于Spring細(xì)數(shù)兩種代理模式之靜態(tài)代理和動態(tài)代理概念及使用的文章就介紹到這了,更多相關(guān)Spring靜態(tài)代理與動態(tài)代理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決IDEA中 Ctrl+ALT+V這個(gè)快捷鍵無法使用的情況

    解決IDEA中 Ctrl+ALT+V這個(gè)快捷鍵無法使用的情況

    這篇文章主要介紹了解決IDEA中 Ctrl+ALT+V這個(gè)快捷鍵無法使用的情況,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Java應(yīng)用服務(wù)器之tomcat會話復(fù)制集群配置的示例詳解

    Java應(yīng)用服務(wù)器之tomcat會話復(fù)制集群配置的示例詳解

    這篇文章主要介紹了Java應(yīng)用服務(wù)器之tomcat會話復(fù)制集群配置的相關(guān)知識,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Restful API中的錯誤處理方法

    Restful API中的錯誤處理方法

    這篇文章主要給大家介紹了關(guān)于Restful API中錯誤處理方法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Java?IO模型之BIO、NIO、AIO三種常見IO模型解析

    Java?IO模型之BIO、NIO、AIO三種常見IO模型解析

    這篇文章主要介紹了今天我們來聊Java?IO模型,BIO、NIO、AIO三種常見IO模型,我們從應(yīng)用調(diào)用的過程中來分析一下整個(gè)IO的執(zhí)行過程,不過在此之前,我們需要簡單的了解一下整個(gè)操作系統(tǒng)的空間布局,需要的朋友可以參考下
    2024-07-07
  • SpringBoot中如何解決讀取properties文件讀取問題

    SpringBoot中如何解決讀取properties文件讀取問題

    這篇文章主要介紹了SpringBoot中如何解決讀取properties文件讀取問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • JVM雙親委派模型知識詳細(xì)總結(jié)

    JVM雙親委派模型知識詳細(xì)總結(jié)

    今天帶各位小伙伴學(xué)習(xí)Java虛擬機(jī)的相關(guān)知識,文中對JVM雙親委派模型作了非常詳細(xì)的介紹,對正在學(xué)習(xí)java的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-05-05
  • struts2實(shí)現(xiàn)文件上傳顯示進(jìn)度條效果

    struts2實(shí)現(xiàn)文件上傳顯示進(jìn)度條效果

    這篇文章主要為大家詳細(xì)介紹了struts2實(shí)現(xiàn)文件上傳顯示進(jìn)度條效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • 使用java實(shí)現(xiàn)各種數(shù)據(jù)統(tǒng)計(jì)圖(柱形圖,餅圖,折線圖)

    使用java實(shí)現(xiàn)各種數(shù)據(jù)統(tǒng)計(jì)圖(柱形圖,餅圖,折線圖)

    用Jfree實(shí)現(xiàn)條形柱狀圖表,java代碼實(shí)現(xiàn)??山?jīng)常用于報(bào)表的制作,代碼自動生成后可以自由查看。可以自由配置圖表的各個(gè)屬性,用來達(dá)到自己的要求和目的。本文給大家介紹使用java實(shí)現(xiàn)各種數(shù)據(jù)統(tǒng)計(jì)圖(柱形圖,餅圖,折線圖),需要的朋友可以參考下
    2015-10-10
  • springboot訪問template下的html頁面的實(shí)現(xiàn)配置

    springboot訪問template下的html頁面的實(shí)現(xiàn)配置

    這篇文章主要介紹了springboot訪問template下的html頁面的實(shí)現(xiàn)配置,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 詳解Elasticsearch如何把一個(gè)索引變?yōu)橹蛔x

    詳解Elasticsearch如何把一個(gè)索引變?yōu)橹蛔x

    這篇文章主要為大家介紹了詳解Elasticsearch如何把一個(gè)索引變?yōu)橹蛔x示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02

最新評論