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

Java代理模式與動態(tài)代理之間的關系以及概念

 更新時間:2023年02月20日 15:16:26   作者:綠仔牛奶_  
代理模式是開發(fā)中常見的一種設計模式,使用代理模式可以很好的對程序進行橫向擴展。動態(tài)代理:代理類在程序運行時被創(chuàng)建的代理方式。關鍵在于動態(tài),程序具有了動態(tài)特性,可以在運行期間根據(jù)不同的目標對象生成動態(tài)代理對象

什么是代理模式

代理模式是開發(fā)中常見的一種設計模式,使用代理模式可以很好的對程序進行橫向擴展。代理,顧名思義就是一個真實對象會存在一個代理對象,并且代理對象可以替真實對象完成相應操作,外部通過代理對象來訪問真實對象并且還可以在代理對象中進行額外操作的擴展。

代理模式的特征是擁有接口、代理類、被代理類。并且代理類與被代理類同時實現(xiàn)該接口。代理類與被代理類之間通常存在一定關聯(lián),設計時會在代理類中注冊一個被代理類的對象用于調(diào)用代理類的方法。這也印證了代理對象依然是執(zhí)行的真實對象的方法

代理模式又分為靜態(tài)代理和動態(tài)代理

靜態(tài)代理

靜態(tài)代理,關鍵字靜態(tài)是指在程序運行之前編譯時就已經(jīng)確定了代理類、被代理類、接口。

下面列舉兩個示例展示靜態(tài)代理:

學生通過班長交班費,班長作為學生的代理,學生是被代理,具有同一行為就是交班費,這個行為我們用接口進行約束

程序:

// 接口
public interface Person {void giveMoney();}
// 學生類--> 被代理類
public class Student implements Person{
  private String name;
  public Student(String name) {this.name = name;}
  public void giveMoney() {
    System.out.println(name+"同學上交50元班費");
  }
}
// 學生代理類
public class StuProxy implements Person{
  private Student stu;
  public StuProxy(Student stu) {
    if (stu.getClass() == Student.class) {
      this.stu = stu;
    }
  }
  public void giveMoney() {stu.giveMoney();}
}

測試:

public static void main(String[] args) {
  // 獲取學生實例  
  Student stu = new Student("張三");
  // 學生找交錢給班長  學生找到代理
  StuProxy stuProxy = new StuProxy(stu);
  // 班長交給老師  代理交錢(交的是學生的錢)
  stuProxy.giveMoney();
}

房屋租賃,租客通過中介找房源,租客為被代理類,中介為代理類,接口聲明租房方法

// 接口
public interface Rent {void doRent();}
// 被代理類
public class Renter implements Rent{
  public void doRent() {
    System.out.println("租客租房了");
  }
}
// 代理類
public class RentProxy implements Rent{
  private Renter renter;
  public RentProxy(Renter renter) {
    if (renter.getClass()==Renter.class)
      this.renter = renter;
  }
  public void doRent() {renter.doRent();}
}

測試:

public static void main(String[] args) {
  // 創(chuàng)建租客
  Renter renter = new Renter();
  // 租客找到中介
  RentProxy rentProxy = new RentProxy(renter);
  // 租客租房
  rentProxy.doRent();
}

上述兩個示例,向代理類中注入被代理對象的方式都是通過構(gòu)造器注入,當然也可以通過set方法注入

下面演示如果需要在已經(jīng)編寫好的代理類的輸出中添加其他操作時的操作比如打印一個日志,在不修改源代碼的情況下擴展

// 下面是最經(jīng)典的Service層的寫法
public interface UserService {
    void del();
    void select();
}
public class UserServiceImpl implements UserService{
    public void del() {
        System.out.println("刪除操作");
    }
    public void select() {
        System.out.println("查詢操作");
    }
}

假設現(xiàn)在我們需要在每一次執(zhí)行操作前后打印一次執(zhí)行日志,并且不能修改源代碼那么就可以用到代理模式,將UserServiceImpl作為被代理類,擴展代理類如下:

public class UserServiceImplProxy implements UserService{
  private UserServiceImpl userService;
  // set注入
  public void setUserService(UserServiceImpl userService) {
    this.userService = userService;
  }
  public void del() {
    printLog();
    userService.del();
  }
  public void select() {
    printLog();
    userService.select();
  }
  private void printLog(){
    System.out.println("執(zhí)行時間="+new Date());
  }
}

動態(tài)代理

動態(tài)代理:代理類在程序運行時被創(chuàng)建的代理方式。

關鍵在于動態(tài),程序具有了動態(tài)特性,可以在運行期間根據(jù)不同的目標對象生成動態(tài)代理對象,并且可以通過動態(tài)代理對象對目標對象(真實對象)進行功能性補強。大白話來講就是,可以在程序運行期間額外的對真實對象功能進行擴展。

此處的動態(tài)代理對象不是通過預先編寫好的程序生成的,而是運行期間由于用戶需求或者說是代碼的指示生成的

動態(tài)代理分為兩種:一類是基于接口實現(xiàn)的動態(tài)代理,另一類是基于類的動態(tài)代理

基于接口的動態(tài)代理–JDK動態(tài)代理通過反射完成,基于類實現(xiàn)的–>cglib

JDK動態(tài)代理核心:Proxy類、InvocationHandler接口、要參與代理的目標類必須實現(xiàn)對應接口,比如上述的Student必須實現(xiàn)Person接口。

繼續(xù)以上述學生交班費為例,更改為動態(tài)代理模式:

JDK動態(tài)代理中間類:該類需要實現(xiàn)InvocationHandler接口

// JDK動態(tài)代理中間類
public class ProxyInvocationHandler implements InvocationHandler {
  // 被代理的對象
  private Object target;
  // ser方法注入?yún)?shù)
  public void setTarget(Object target) {this.target = target;}
  // 生成動態(tài)代理類
  public Object getProxy(){
    return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
  }
  // 處理代理實例,并返回結(jié)果
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object result = method.invoke(target,args);
    return result;
  }
}

測試:

public static void main(String[] args) {
  // 獲取真實角色
  Student stu = new Student("張三三");
  // 動態(tài)代理中間類對象
  InvocationHandlerProxyStudent proxyStudent = new InvocationHandlerProxyStudent();
  proxyStudent.setStu(stu);
  // 代理類實例
  Person proxy = (Person) proxyStudent.getProxy();
  // 代理類實例調(diào)用方法
  proxy.giveMoney();
}

上述程序,我們利用Proxy來生成代理類:

public Object getProxy(){
  return Proxy.newProxyInstance(this.getClass().getClassLoader(),
stu.getClass().getInterfaces(),this);
}

Proxy提供了靜態(tài)的獲取Proxy代理類的方法newProxyInstance,三個參數(shù)分別是1.類加載器 2.代理對象實現(xiàn)的接口 3. 調(diào)用處理程序(InvocationHandler)

在InvocationHandler官方文檔就已經(jīng)指出,每一個代理實例都關聯(lián)有一個InvocationHandler調(diào)用處理程序,所以這里填this即可

在使用代理類的時候首先我們創(chuàng)建需要被代理的真實對象和動態(tài)代理中間類的對象,用set方法將真實對象交給中間類中的代理對象。在調(diào)用上述getProxy方法獲取代理類。動態(tài)代理相對于靜態(tài)代理有些難以理解,這是因為靜態(tài)代理的代理類可以在程序中顯式的被看到,而動態(tài)代理中的代理類文件是緩存在Java虛擬機,類名叫$Proxy0。

在虛擬機中生成的代理類中就會將我們所調(diào)用的方法內(nèi)置,我們在執(zhí)行proxy.giveMoney()的同時,實際上是將giveMoney()方法作為參數(shù)傳進invoke()的參數(shù)中去,而此時我們就可以將其他的操作交給invoke,由于所有代理對象在執(zhí)行時最終都會走invoke方法,所以也為我們的開發(fā)節(jié)省大量代碼

到此這篇關于Java代理模式與動態(tài)代理之間的關系以及概念的文章就介紹到這了,更多相關Java代理模式與動態(tài)代理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java拆箱與裝箱實例詳解

    Java拆箱與裝箱實例詳解

    這篇文章主要介紹了Java拆箱與裝箱,結(jié)合實例形式詳細分析了Java拆箱與裝箱相關的數(shù)據(jù)類型轉(zhuǎn)換操作技巧,需要的朋友可以參考下
    2019-11-11
  • 基于java查找最長字符串代碼實例

    基于java查找最長字符串代碼實例

    這篇文章主要介紹了基于java查找最長字符串代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • Javadoc標簽和Javadoc注釋規(guī)范說明

    Javadoc標簽和Javadoc注釋規(guī)范說明

    這篇文章主要介紹了Javadoc標簽和Javadoc注釋規(guī)范說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Action訪問Servlet的API的簡單實例

    Action訪問Servlet的API的簡單實例

    下面小編就為大家?guī)硪黄狝ction訪問Servlet的API的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • java?線程池如何執(zhí)行策略又拒絕哪些策略

    java?線程池如何執(zhí)行策略又拒絕哪些策略

    這篇文章主要介紹了java?線程池如何執(zhí)行策略又拒絕哪些策略,文章通過線程池的執(zhí)行方法?execute()?展開全篇內(nèi)容,需要的小伙伴可以參考一下
    2022-05-05
  • Spring 中 BeanFactoryPostProcessor 的作用和示例源碼分析

    Spring 中 BeanFactoryPostProcessor 的作用和示例源碼分析

    Spring的BeanFactoryPostProcessor是容器初始化的擴展接口,允許在Bean實例化前修改或擴展Bean的配置元數(shù)據(jù),本文給大家介紹Spring 中 BeanFactoryPostProcessor 的作用和示例源碼分析,感興趣的朋友一起看看吧
    2025-03-03
  • Spring中一個少見的引介增強IntroductionAdvisor

    Spring中一個少見的引介增強IntroductionAdvisor

    這篇文章主要為大家介紹了Spring中一個少見的引介增強IntroductionAdvisor實戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • IntelliJ IDEA之高效代碼插件RainBow Brackets詳解

    IntelliJ IDEA之高效代碼插件RainBow Brackets詳解

    這篇文章主要介紹了IntelliJ IDEA之高效代碼插件RainBow Brackets詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • MyBatis insert語句返回主鍵和selectKey標簽方式

    MyBatis insert語句返回主鍵和selectKey標簽方式

    這篇文章主要介紹了MyBatis insert語句返回主鍵和selectKey標簽方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java GUI界面初步入門示例【AWT包】

    java GUI界面初步入門示例【AWT包】

    這篇文章主要介紹了java GUI界面,結(jié)合簡單實例形式分析了java使用AWT包進行圖形界面操作相關使用技巧,需要的朋友可以參考下
    2020-01-01

最新評論

丰城市| 澄城县| 朔州市| 盐源县| 卫辉市| 岚皋县| 大埔区| 和龙市| 内丘县| 东宁县| 阿勒泰市| 桂东县| 越西县| 天台县| 滨海县| 高唐县| 东城区| 南和县| 青岛市| 林周县| 万州区| 武宁县| 垦利县| 新泰市| 兴宁市| 哈尔滨市| 玛纳斯县| 阜新市| 广汉市| 新绛县| 苗栗市| 永川市| 浑源县| 赤城县| 襄城县| 阆中市| 于都县| 建阳市| 广河县| 镇康县| 逊克县|