溫馨提示×

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

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

Java中代理的原理是什么

發(fā)布時(shí)間:2021-05-10 17:31:33 來(lái)源:億速云 閱讀:155 作者:Leah 欄目:編程語(yǔ)言

這篇文章給大家介紹Java中代理的原理是什么,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

Java可以用來(lái)干什么

Java主要應(yīng)用于:1. web開(kāi)發(fā);2. Android開(kāi)發(fā);3. 客戶端開(kāi)發(fā);4. 網(wǎng)頁(yè)開(kāi)發(fā);5. 企業(yè)級(jí)應(yīng)用開(kāi)發(fā);6. Java大數(shù)據(jù)開(kāi)發(fā);7.游戲開(kāi)發(fā)等。

1.什么是代理

動(dòng)態(tài)代理技術(shù)是整個(gè)java技術(shù)中最重要的一個(gè)技術(shù),它是學(xué)習(xí)java框架的基礎(chǔ),不會(huì)動(dòng)態(tài)代理技術(shù),那么在學(xué)習(xí)Spring這些框架時(shí)是學(xué)不明白的。

  動(dòng)態(tài)代理技術(shù)就是用來(lái)產(chǎn)生一個(gè)對(duì)象的代理對(duì)象的。在開(kāi)發(fā)中為什么需要為一個(gè)對(duì)象產(chǎn)生代理對(duì)象呢?
  舉一個(gè)現(xiàn)實(shí)生活中的例子:歌星或者明星都有一個(gè)自己的經(jīng)紀(jì)人,這個(gè)經(jīng)紀(jì)人就是他們的代理人,當(dāng)我們需要找明星表演時(shí),不能直接找到該明星,只能是找明星的代理人。比如劉德華在現(xiàn)實(shí)生活中非常有名,會(huì)唱歌,會(huì)跳舞,會(huì)拍戲,劉德華在沒(méi)有出名之前,我們可以直接找他唱歌,跳舞,拍戲,劉德華出名之后,他干的第一件事就是找一個(gè)經(jīng)紀(jì)人,這個(gè)經(jīng)紀(jì)人就是劉德華的代理人(代理),當(dāng)我們需要找劉德華表演時(shí),不能直接找到劉德華了(劉德華說(shuō),你找我代理人商談具體事宜吧!),只能是找劉德華的代理人,因此劉德華這個(gè)代理人存在的價(jià)值就是攔截我們對(duì)劉德華的直接訪問(wèn)!
  這個(gè)現(xiàn)實(shí)中的例子和我們?cè)陂_(kāi)發(fā)中是一樣的,我們?cè)陂_(kāi)發(fā)中之所以要產(chǎn)生一個(gè)對(duì)象的代理對(duì)象,主要用于攔截對(duì)真實(shí)業(yè)務(wù)對(duì)象的訪問(wèn)。那么代理對(duì)象應(yīng)該具有什么方法呢?代理對(duì)象應(yīng)該具有和目標(biāo)對(duì)象相同的方法

  所以在這里明確代理對(duì)象的兩個(gè)概念:
    1、代理對(duì)象存在的價(jià)值主要用于攔截對(duì)真實(shí)業(yè)務(wù)對(duì)象的訪問(wèn)。
    2、代理對(duì)象應(yīng)該具有和目標(biāo)對(duì)象(真實(shí)業(yè)務(wù)對(duì)象)相同的方法。劉德華(真實(shí)業(yè)務(wù)對(duì)象)會(huì)唱歌,會(huì)跳舞,會(huì)拍戲,我們現(xiàn)在不能直接找他唱歌,跳舞,拍戲了,只能找他的代理人(代理對(duì)象)唱歌,跳舞,拍戲,一個(gè)人要想成為劉德華的代理人,那么他必須具有和劉德華一樣的行為(會(huì)唱歌,會(huì)跳舞,會(huì)拍戲),劉德華有什么方法,他(代理人)就要有什么方法,我們找劉德華的代理人唱歌,跳舞,拍戲,但是代理人不是真的懂得唱歌,跳舞,拍戲的,真正懂得唱歌,跳舞,拍戲的是劉德華,在現(xiàn)實(shí)中的例子就是我們要找劉德華唱歌,跳舞,拍戲,那么只能先找他的經(jīng)紀(jì)人,交錢(qián)給他的經(jīng)紀(jì)人,然后經(jīng)紀(jì)人再讓劉德華去唱歌,跳舞,拍戲。

2.代理的分類(lèi)

靜態(tài)代理:代理類(lèi)和委托類(lèi)在代碼運(yùn)行之前關(guān)系就已經(jīng)確定了,也就是說(shuō)在代理類(lèi)的代碼一開(kāi)始就已經(jīng)存在了。

動(dòng)態(tài)代理:動(dòng)態(tài)代理類(lèi)的字節(jié)碼在程序運(yùn)行的時(shí)候生成。

3.Java中的代理

"java.lang.reflect.Proxy"類(lèi)介紹

現(xiàn)在要生成某一個(gè)對(duì)象的代理對(duì)象,這個(gè)代理對(duì)象通常也要編寫(xiě)一個(gè)類(lèi)來(lái)生成,所以首先要編寫(xiě)用于生成代理對(duì)象的類(lèi)。在java中如何用程序去生成一個(gè)對(duì)象的代理對(duì)象呢,java在JDK1.5之后提供了一個(gè)"java.lang.reflect.Proxy"類(lèi),通過(guò)"Proxy"類(lèi)提供的一個(gè)newProxyInstance方法用來(lái)創(chuàng)建一個(gè)對(duì)象的代理對(duì)象,如下所示:

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

newProxyInstance方法用來(lái)返回一個(gè)代理對(duì)象,這個(gè)方法總共有3個(gè)參數(shù),ClassLoader loader用來(lái)指明生成代理對(duì)象使用哪個(gè)類(lèi)裝載器,Class<?>[] interfaces用來(lái)指明生成哪個(gè)對(duì)象的代理對(duì)象,通過(guò)接口指定,InvocationHandler h用來(lái)指明產(chǎn)生的這個(gè)代理對(duì)象要做什么事情。所以我們只需要調(diào)用newProxyInstance方法就可以得到某一個(gè)對(duì)象的代理對(duì)象了。

編寫(xiě)生成代理對(duì)象的類(lèi)

在java中規(guī)定,要想產(chǎn)生一個(gè)對(duì)象的代理對(duì)象,那么這個(gè)對(duì)象必須要有一個(gè)接口,所以我們第一步就是設(shè)計(jì)這個(gè)對(duì)象的接口,在接口中定義這個(gè)對(duì)象所具有的行為(方法)

StduentInterface.java--定義對(duì)象的行為接口

public interface StduentInterface {
 public int insertStudent(Student student);
}

StudentDao.java--定義目標(biāo)業(yè)務(wù)對(duì)象類(lèi)

public class StudentDAO implements StduentInterface {
 @Override
 public int insertStudent(Student student) {
  // 以下這段代碼是業(yè)務(wù)邏輯
  return null == student ? 0 : 1;
 }
}

創(chuàng)建靜態(tài)代理

public class StudentStaticProxyDAO {
 private StudentDAO studentDAO;
 public StudentStaticProxyDAO(StudentDAO studentDAO) {
  this.studentDAO = studentDAO;
 }
 public int insertStudent(Student student) {
  Logger.info("開(kāi)始插入一個(gè)學(xué)生記錄: " + student.toString());
  int number = studentDAO.insertStudent(student);
  Logger.info("插入 " + number + " 條學(xué)生記錄");
  return number;
 }
}

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

public class LoggerDynamicProxy implements InvocationHandler{
 private Object target;
 public LoggerDynamicProxy(Object obj) {
  this.target = obj;
 }
 /**
  * 動(dòng)態(tài)代理類(lèi)中的 invoke 方法
  *
  * 三個(gè)參數(shù)的意義:
  *
  * proxy :代理對(duì)象
  * method : 委托類(lèi)中要調(diào)用的方法
  * args :method 方法的參數(shù)
  */
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  Logger.info("before 業(yè)務(wù)方法調(diào)用之前");
  Object obj = method.invoke(target, args);
  Logger.info("before 業(yè)務(wù)方法調(diào)用之前");
  return obj;
 }
}

測(cè)試類(lèi)

public class ProxyTest {
 public static void main(String[] args) {
  /**
   * 基礎(chǔ)組件準(zhǔn)備
   */
  StudentDAO studentDao = new StudentDAO();
  Student student = new Student(100000);
  StudentStaticProxyDAO studentProxyDAO = new StudentStaticProxyDAO(studentDao);
  /**
   * 測(cè)試委托類(lèi)的功能
   */
  System.out.println(studentDao.insertStudent(student));
  /**
   * 測(cè)試靜態(tài)代理類(lèi)的功能
   */
  System.out.println(studentProxyDAO.insertStudent(student));
  /**
   * 測(cè)試動(dòng)態(tài)代理類(lèi)的功能
   */
  StduentInterface newProxyInstance = (StduentInterface)Proxy.newProxyInstance(studentDao.getClass().getClassLoader(),
    studentDao.getClass().getInterfaces(),
    new LoggerDynamicProxy(studentDao));
  int insertStudent = newProxyInstance.insertStudent(student);
  System.out.println(insertStudent);
}

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

1
INFO: 開(kāi)始插入一個(gè)學(xué)生記錄: Student [id=100000, name=null]
INFO: 插入 1 條學(xué)生記錄
1
INFO: before 業(yè)務(wù)方法調(diào)用之前
INFO: before 業(yè)務(wù)方法調(diào)用之前
1
INFO: before 業(yè)務(wù)方法調(diào)用之前
INFO: before 業(yè)務(wù)方法調(diào)用之前
1

關(guān)于Java中代理的原理是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向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