亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中的三種代理模式詳解

 更新時間:2023年08月25日 11:34:48   作者:S_polygon  
這篇文章主要介紹了Java中的三種代理模式詳解,代理模式的關鍵點是:代理對象與目標對象.代理對象是對目標對象的擴展,并會調用目標對象,文中提供了部分代碼,需要的朋友可以參考下

Java代理模式

什么是代理模式?

代理(Proxy)是一種設計模式,為其他對象提供一種代理以控制對這個對象的訪問。

代理模式的組成

  • 抽象角色:通過接口或抽象類聲明真實角色實現(xiàn)的業(yè)務方法。
  • 代理角色:實現(xiàn)抽象角色,是真實角色的代理,通過真實角色的業(yè)務邏輯方法來實現(xiàn)抽象方法,并可以附加自己的操作。
  • 真實角色:實現(xiàn)抽象角色,定義真實角色所要實現(xiàn)的業(yè)務邏輯,供代理角色調用。

代理模式的優(yōu)點

(1).職責清晰

真實的角色就是實現(xiàn)實際的[業(yè)務邏輯,不用關心其他非本職責的事務,通過后期的代理完成一件完成事務,附帶的結果就是編程簡潔清晰。

(2).代理對象可以在客戶端和目標對象之間起到中介的作用,這樣起到了中介的作用和保護了目標對象的作用。

(3).高擴展性

代理模式的關鍵點是:代理對象與目標對象.代理對象是對目標對象的擴展,并會調用目標對象。

1、靜態(tài)代理

? 靜態(tài)代理在使用時,需要定義接口或者父類,被代理對象與代理對象一起實現(xiàn)相同的接口或者是繼承相同父類。

步驟1:創(chuàng)建UserDao.java接口

步驟2:創(chuàng)建UserDaoImpl.java(UserDao接口實現(xiàn)類)

步驟3:創(chuàng)建代理類Proxy01.java(實現(xiàn)UserDao接口)

/**
 * 代理對象,靜態(tài)代理
 * */
public class Proxy01 implements UserDao {
    //接受保存目標對象
    UserDao target;
    public Proxy01() {
    }
    public Proxy01(UserDao target) {
        this.target = target;
    }
    @Override
    public void getUser() {
        System.out.println("事務開始");
        target.getUser();
        System.out.println("事務結束");
    }
}

步驟4:測試Proxy01_test.java

/**
 * 測試靜態(tài)代理
 * 靜態(tài)代理:修改被代理類中的代理方法,需要修改代理類中的方法
 * 缺點:
 *
 * 因為代理對象需要與目標對象實現(xiàn)一樣的接口,所以會有很多代理類,類太多.同時,一旦接口增加方法,目標對象與代理對象都要維護.
 * */
public class Proxy01_test {
    public static void main(String[] args) {
        //目標對象
        UserDao target = new UserDaoImpl();
        //代理對象,把目標對象傳給代理對象,建立代理關系
        Proxy01 proxy = new Proxy01(target);
        proxy.getUser();//執(zhí)行的是代理的方法
    }
}

執(zhí)行結果:

在這里插入圖片描述

總結:

  • 靜態(tài)代理在使用時,需要定義接口或者父類,被代理對象與代理對象一起實現(xiàn)接口或繼承相同 的父類

缺點:

  • 因為代理對象需要和被代理對象實現(xiàn)相同的接口或父類,所以會有太多的代理類
  • 一旦接口中增加了方法后,被代理對象和代理對象都需要維護(非常麻煩,不方便)

2、jdk動態(tài)代理

JDK中動態(tài)代理類只需要使用java.lang.reflect.Proxy.newProxyInstance方法,該方法需要接收三個參數(shù),完整的寫法是:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )

注意該方法是在Proxy類中是靜態(tài)方法,且接收的三個參數(shù)依次為:

  • ClassLoader loader:指定當前目標對象使用類加載器,獲取加載器的方法是固定的
  • Class<?>[] interfaces:目標對象實現(xiàn)的接口類型,使用泛型方式確認類型,獲取接口類型的方法是固定的
  • InvocationHandler h;事件處理,執(zhí)行目標對象的方法時,會觸發(fā)事件處理器的方法,會把當前執(zhí)行目標對象的方法作為參數(shù)傳入

步驟1:創(chuàng)建UserDao.java接口

步驟2:創(chuàng)建UserDaoImpl.java(UserDao接口實現(xiàn)類)

步驟3:創(chuàng)建代理類Proxy02.java

/**
 * jdk動態(tài)代理類
 * */
public class Proxy02 {
    //維護一個目標對象
    private Object target;
    public Proxy02(Object target) {
        this.target = target;
    }
    //給目標對象生成代理對象
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this::invoke);
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("開始事務2");
        //執(zhí)行目標對象方法
        Object returnValue = method.invoke(target, args);
        System.out.println("提交事務2");
        return returnValue;
    }
}

步驟4:測試Proxy02_test.java

/**
 * 測試jdk動態(tài)代理
 * 代理對象不需要實現(xiàn)接口,但是目標對象一定要實現(xiàn)接口,否則不能用動態(tài)代理
 * 接口中增加方法時只用在實現(xiàn)類中增加方法,不用修改代理類。
 * */
public class Proxy02_test {
    public static void main(String[] args) {
        //目標對象
        UserDao target = new UserDaoImpl();
        // 【原始的類型 class top.polygon.proxy01.dao.impl.UserDaoImpl】
        System.out.println(target.getClass());
        // 給目標對象,創(chuàng)建代理對象
        UserDao proxy = (UserDao) new Proxy02(target).getProxyInstance();
        // class $Proxy0   內存中動態(tài)生成的代理對象
        System.out.println(proxy.getClass());
        proxy.getUser();//執(zhí)行的是代理的方法
        proxy.insertUser();
    }
}

運行結果:

在這里插入圖片描述

總結:

代理對象不需要實現(xiàn)接口,但是目標對象一定要實現(xiàn)接口,否則不能用動態(tài)代理

3、cglib動態(tài)代理

靜態(tài)代理和jdk動態(tài)代理都要求目標對象實現(xiàn)接口,

cglib動態(tài)代理,使用以目標對象子類的方式實現(xiàn)代理,(當目標對象是一個單獨的對象,沒有實現(xiàn)任何接口時使用).

Cglib代理,也叫作子類代理,它是在內存中構建一個子類對象從而實現(xiàn)對目標對象功能的擴展。Cglib是一個強大的高性能的代碼生成包,它可以在運行期擴展Java類與實現(xiàn)Java接口。它廣泛的被許多AOP的框架使用,為其提供方法的interception(攔截),例如大家所熟知的Spring AOP。

? Cglib包的底層是通過使用一個小而快的字節(jié)碼處理框架ASM來轉換字節(jié)碼并生成新的類。

Cglib子類代理需要注意的是:

  • 需要引入cglib的jar包
  • 代理的類不能是final,否則報錯
  • 目標對象的方法如果有final/static,那么不會被攔截,即不會執(zhí)行目標對象額外的業(yè)務方法。

實現(xiàn)步驟:

步驟1:引入jar包

       <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>

步驟2:創(chuàng)建被代理的類UserDaoImpl.java

public class UserDaoImpl{
    public void getUser() {
        System.out.println("cglib動態(tài)代理:得到用戶信息");
    }
    public void insertUser() {
        System.out.println("cglib動態(tài)代理:添加用戶");
    }
}

步驟3:創(chuàng)建代理類Proxy03.java

/**
 * cglib動態(tài)代理
 *
 * */
public class Proxy03 implements MethodInterceptor {
    //維護目標對象
    private Object target;
    public Proxy03(Object target) {
        this.target = target;
    }
    //給目標對象創(chuàng)建一個代理對象
    public Object getProxyInstance(){
        //1.工具類
        Enhancer en = new Enhancer();
        //2.設置父類
        en.setSuperclass(target.getClass());
        //3.設置回調函數(shù)
        en.setCallback(this);
        //4.創(chuàng)建子類(代理對象)
        return en.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("開始事務...");
        //執(zhí)行目標對象的方法
        Object returnValue = method.invoke(target, objects);
        System.out.println("提交事務...");
        return returnValue;
    }
}

步驟4:測試Proxy03_test.java

public class Proxy03_test {
    public static void main(String[] args) {
        //目標對象
        UserDao target = new UserDaoImpl();
        System.out.println(target.getClass());
        // 給目標對象,創(chuàng)建代理對象
        UserDao proxy = (UserDao) new Proxy03(target).getProxyInstance();
        System.out.println(proxy.getClass());
        proxy.getUser();//執(zhí)行的是代理的方法
        proxy.insertUser();
    }
}

運行結果

在這里插入圖片描述

到此這篇關于Java中的三種代理模式詳解的文章就介紹到這了,更多相關Java代理模式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • spring事務@Transactional失效原因及解決辦法小結

    spring事務@Transactional失效原因及解決辦法小結

    今天就跟大家聊聊有關spring中@Transactional失效原因及解決辦法小結,主要從三個方面考慮,具有一定的參考價值,感興趣的可以了解一下
    2023-08-08
  • Java中淺拷貝和深拷貝詳解

    Java中淺拷貝和深拷貝詳解

    大家好,本篇文章主要講的是Java中淺拷貝和深拷貝詳解,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • 基于Java HttpClient和Htmlparser實現(xiàn)網絡爬蟲代碼

    基于Java HttpClient和Htmlparser實現(xiàn)網絡爬蟲代碼

    這篇文章主要介紹了基于Java HttpClient和Htmlparser實現(xiàn)網絡爬蟲代碼的相關資料,需要的朋友可以參考下
    2015-12-12
  • Java中獲取webapp路徑問題詳解

    Java中獲取webapp路徑問題詳解

    這篇文章主要介紹了Java中獲取webapp路徑問題詳解,WebApp是指基于Web的?系統(tǒng)和?應用,其作用是向廣大的最終用戶發(fā)布一組復雜的內容和功能,本文詳解了關于獲取路徑時候可能出現(xiàn)的問題,需要的朋友可以參考下
    2023-07-07
  • Spring?Boot?項目中?JPA?語法的基本使用方法

    Spring?Boot?項目中?JPA?語法的基本使用方法

    這篇文章主要介紹了?Spring?Boot?項目中?JPA?語法的基本使用方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-10-10
  • java開發(fā)SpringBoot參數(shù)校驗過程示例教程

    java開發(fā)SpringBoot參數(shù)校驗過程示例教程

    這篇文章主要為大家介紹了SpringBoot如何進行參數(shù)校驗的過程示例詳解教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2021-10-10
  • Java?自定義注解在登錄驗證的應用示例

    Java?自定義注解在登錄驗證的應用示例

    本文主要介紹了Java?自定義注解在登錄驗證的應用示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 打包SpringBoot程序為exe的案例教程

    打包SpringBoot程序為exe的案例教程

    這篇文章主要介紹了打包SpringBoot程序為exe的案例教程,文中通過圖文講解的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-12-12
  • Java 數(shù)據(jù)結構進階二叉樹題集上

    Java 數(shù)據(jù)結構進階二叉樹題集上

    二叉樹可以簡單理解為對于一個節(jié)點來說,最多擁有一個上級節(jié)點,同時最多具備左右兩個下級節(jié)點的數(shù)據(jù)結構。本文將帶你通過實際題目來熟練掌握
    2022-04-04
  • 詳解IDEA多module項目maven依賴的一些說明

    詳解IDEA多module項目maven依賴的一些說明

    這篇文章主要介紹了詳解IDEA多module項目maven依賴的一些說明,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10

最新評論