一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 深入理解java動態代理的兩種實現方式(JDK/Cglib)

深入理解java動態代理的兩種實現方式(JDK/Cglib)

2020-09-06 14:55PerKins.Zhu Java教程

本篇文章主要介紹了java動態代理的兩種實現方式,詳細的介紹了JDK和Cglib的實現方法,具有一定的參考價值,有興趣的可以了解一下

什么是代理模式?

代理模式:在調用處不直接調用目標類進行操作,而是調用代理類,然后通過代理類來調用目標類進行操作。在代理類調用目標類的前后可以添加一些預處理和后處理操作來完成一些不屬于目標類的功能。

為什么要使用代理模式?

通過代理模式可以實現對目標類調用的控制、在目標類調用前/后進行一些不屬于目標類的操作,如:數據驗證、預處理、后處理、異常處理等

什么是靜態代理什么是動態代理

  1. 靜態代理:代理類只能實現對”特定接口的實現類“進行代理
  2. 動態代理:代理類可以實現對多種類的代理

jdk代理和cglib代理區別在哪里?

  1. jdk動態代理:代理所有“實現的有接口”的目標類
  2. cglib動態代理:代理任意一個目標類,但對final類和方法無法代理

不同點:jdk動態代理的目標類必須實現的有接口,因為在調用Proxy.newProxyInstance()的時候需要傳入目標類的接口類。而cglib不做此限制。    

下面看代碼分析:

定義一個Person接口

java" id="highlighter_454448">
?
1
2
3
4
5
6
package com.zpj.designMode.proxy;
 
//定義一個Person接口
public interface Person {
  public void doWork();
}

添加一個實現類:MrLi

?
1
2
3
4
5
6
7
8
9
10
11
package com.zpj.designMode.proxy;
 
//添加一個實現類
public class MrLi implements Person {
 
  @Override
  public void doWork() {
    System.out.println("-----doWork");
  }
 
}

靜態代理:

添加一個靜態代理類Proxy

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.zpj.designMode.proxy;
 
//靜態代理,代理必須和目標類實現共同的接口
public class Proxy implements Person {
  private Person person;// 被代理人
 
  //這里的目標類型決定了該代理類只能代理實現了Person接口的實例,而不能接收其他類型參數,這也就是靜態代理的局限性
  public Proxy(Person person) {
    this.person = person;
  }
 
  @Override
  public void doWork() {
    System.out.println("doSomething-----start");
    person.doWork();
    System.out.println("doSomething-----end");
  }
 
}

靜態代理測試程序:

?
1
2
3
4
5
6
7
8
9
10
package com.zpj.designMode.proxy;
 
public class Run {
  public static void main(String[] args) {
    MrLi li = new MrLi();
    Proxy proxy = new Proxy(li);
    //調用處直接調用代理進行目標方法的操作。
    proxy.doWork();
  }
}

JDK動態代理:

添加一個代理JDKProxy,該代理實現InvocationHandler接口且覆寫invoke方法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.zpj.designMode.proxy.jdk;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
/***
 @author Perkins Zhu
 @date 2017年3月13日 上午8:41:10
 */
public class JDKProxy implements InvocationHandler {
 
  private Object person;// 被代理人
   
  
  //這里的目標類型為Object,則可以接受任意一種參數作為被代理類,實現了動態代理。但是要注意下面的newProxyInstance()中的參數
  public Object getInstance(Object person) {
    this.person = person;
    //與cglib的區別在于這里構建代理對象的時候需要傳入被代理對象的接口對象,第二個參數。而cglib不需要被代理對象實現任何接口即可   
    return Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), this);
  }
 
 
 
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("doSomething---------start");
    method.invoke(person, args);
    System.out.println("doSomething---------end");
    return null;
  }
 
}

JDK動態代理測試程序

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.zpj.designMode.proxy.jdk;
 
import com.zpj.designMode.proxy.MrLi;
import com.zpj.designMode.proxy.Person;
 
/***
 * @author Perkins Zhu
 * @date 2017年3月13日 上午8:51:31
 */
public class Run {
 
  public static void main(String[] args) {
    Person person = (Person) new JDKProxy().getInstance(new MrLi());
    //注意這里的person不是目標類person,而是代理類person:debug的時候顯示null,有'$'標識符
    person.doWork();
  }
}

Cglib動態代理:

添加一個CglibProxy代理,同時實現MethodInterceptor接口。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.zpj.designMode.proxy.cglib;
 
import java.lang.reflect.Method;
 
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
 
/***
 * @author Perkins Zhu
 * @date 2017年3月13日 上午9:02:54
 */
public class CglibProxy implements MethodInterceptor {
  private Object targetObject;
 
  // 這里的目標類型為Object,則可以接受任意一種參數作為被代理類,實現了動態代理
  public Object getInstance(Object target) {
    this.targetObject = target;
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(target.getClass());
    enhancer.setCallback(this);
    //注意該處代理的創建過程
    Object proxyObj = enhancer.create();
    return proxyObj;// 返回代理對象
  }
 
  @Override
  public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    Object obj = null;
    System.out.println("doSomething---------start");
    obj = method.invoke(targetObject, args);
    System.out.println("doSomething---------end");
    return obj;
  }
 
}

Cglib動態代理測試程序

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.zpj.designMode.proxy.cglib;
 
import com.zpj.designMode.proxy.MrLi;
import com.zpj.designMode.proxy.Person;
 
/***
 @author Perkins Zhu
 @date 2017年3月13日 上午9:07:38
 */
public class Run {
 
  public static void main(String[] args) {
    Person person = (Person)new CglibProxy().getInstance(new MrLi());
    person.doWork();
  }
}

仔細對比Proxy、CglibProxy和JDKProxy區分靜態代理、JDK動態代理和Cglib動態代理的異同點!

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/PerkinsZhu/p/6549211.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日本乱子| 经典三级四虎在线观看 | 国产精品久久久久久久人人看 | 毛片免费网站 | 久久re亚洲在线视频 | 色狠狠色狠狠综合天天 | 日本卡一卡2卡3卡4精品卡无人区 | caoporm国产精品视频免费 | 亚洲高清在线精品一区 | 国产在线乱子伦一区二区 | 午夜视频一区 | 被18号每天强行榨干acg | 午夜想想爱 | 欧美国产日韩1区俺去了 | 日韩在线视频在线 | avtt一区| juliaann厨房大战 | 草啪啪| 国产视频自拍一区 | 亚洲人成激情在线播放 | 婷婷久久热99在线精品 | pron欧美| 国产免费又粗又猛又爽视频国产 | 女学生被老师调教在教室 | 成人免费一区二区三区在线观看 | 美女把腿开让我 | 2018天天拍拍拍免费视频 | 动漫精品午夜在线播放 | 啊好爽视频 | 日韩精品亚洲一级在线观看 | 啊用力好大粗黑人小说 | 草草影院在线 | 500福利第一巨人导航 | 男女全黄h全肉细节文 | 国产在线视频色综合 | 亚洲国产成人在线 | 教师系列 大桥未久在线 | 91gmail国产| 国产精品视频一区二区三区经 | ai换脸杨颖被啪在线观看 | 日韩在线观看一区二区不卡视频 |