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

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

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

服務器之家 - 編程語言 - Java教程 - 老生常談設計模式之動態代理

老生常談設計模式之動態代理

2020-11-13 10:40Java教程網 Java教程

下面小編就為大家帶來一篇老生常談設計模式之動態代理。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

一、動態代理概念

動態代理分為JDK動態代理和cglib動態代理兩種方式。

jdk動態代理是由Java內部的反射機制來實現的,cglib動態代理底層則是借助asm來實現的。

總的來說,反射機制在生成類的過程中比較高效,而asm在生成類之后的相關執行過程中比較高效(可以通過將asm生成的類進行緩存,這樣解決asm生成類過程低效問題)。

還有一點必須注意:jdk動態代理的應用前提,必須是目標類基于統一的接口。如果沒有上述前提,jdk動態代理不能應用

由此可以看出,jdk動態代理有一定的局限性,cglib這種第三方類庫實現的動態代理應用更加廣泛,且在效率上更有優勢。

二、JDK動態代理

以下代碼使用代理模式實現一個大小寫字符轉換的功能。

定義接口和實現類:

ISomeService接口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;
 
/**
 * 接口類
 *
 * @author Root
 */
public interface ISomeService {
  
  String doFirst();
  
  void doSecond();
}

SomeServiceImpl實現類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;
 
/**
 * 實現類
 *
 * @author Root
 */
public class SomeServiceImpl implements ISomeService {
 
  @Override
  public String doFirst() {
    System.out.println("執行doFirst()...");
    String result = "abcde";
    return result;
  }
 
  @Override
  public void doSecond() {
    System.out.println("執行doSecond()...");
  }
 
}

JDK動態代理類:

?
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
37
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
public class Main {
  public static void main(String[] args) {
 
    final ISomeService target = new SomeServiceImpl();
    
    // 使用JDK的Proxy動態代理,要求目標類和代理類必須實現相同的接口,因為其底層的執行原理與靜態代理的相同
    ISomeService service = (ISomeService) Proxy.newProxyInstance(
        // 目標類的類加載器
        target.getClass().getClassLoader(),
        // 目標類所實現的所有接口
        target.getClass().getInterfaces(),
        new InvocationHandler() {
          // proxy:代理對象
          // method:目標方法
          // args:目標方法的參數列表
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 調用目標方法
            Object result = method.invoke(target, args);
            if (result != null) {
              result = ((String) result).toUpperCase();
            }
            return result;
          }
        });
    String result = service.doFirst();
    System.out.println(result);
 
    service.doSecond();
  }
}

三、cglib動態代理

Cglib是一個優秀的動態代理框架,它的底層使用ASM在內存中動態的生成被代理類的子類,使用CGLIB即使代理類沒有實現任何接口也可以實現動態代理功能。CGLIB具有簡單易用,它的運行速度要遠遠快于JDK的Proxy動態代理:

CGLIB的核心類:

net.sf.cglib.proxy.Enhancer – 主要的增強類

net.sf.cglib.proxy.MethodInterceptor – 主要的方法攔截類,它是Callback接口的子接口,需要用戶實現

net.sf.cglib.proxy.MethodProxy – JDK的java.lang.reflect.Method類的代理類,可以方便的實現對源對象方法的調用,如使用:

Object o = methodProxy.invokeSuper(proxy, args);//雖然第一個參數是被代理對象,也不會出現死循環的問題。

net.sf.cglib.proxy.MethodInterceptor接口是最通用的回調(callback)類型,它經常被基于代理的AOP用來實現攔截(intercept)方法的調用。這個接口只定義了一個方法

public Object intercept(Object object, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable;

第一個參數是代理對像,第二和第三個參數分別是攔截的方法和方法的參數。原來的方法可能通過使用java.lang.reflect.Method對象的一般反射調用,或者使用 net.sf.cglib.proxy.MethodProxy對象調用。net.sf.cglib.proxy.MethodProxy通常被首選使用,因為它更快。

以下程序實現了大小寫轉換的功能:

實現類SomeService:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.ietree.basicskill.designpattern.dynamicproxy.cglib;
 
/**
 * 實現類
 *
 * @author Root
 */
public class SomeService {
 
  public String doFirst() {
    System.out.println("執行doFirst()...");
    String result = "abcde";
    return result;
  }
 
  public void doSecond() {
    System.out.println("執行doSecond()...");
  }
 
}

代理類MyCglibFactory:

?
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
37
38
39
package com.ietree.basicskill.designpattern.dynamicproxy.cglib;
 
import java.lang.reflect.Method;
 
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
 
public class MyCglibFactory implements MethodInterceptor {
 
  private SomeService target;
  
  public MyCglibFactory() {
    super();
    target = new SomeService();
  }
 
  public SomeService myCglibCreator() {
    // 創建增強器對象
    Enhancer enhancer = new Enhancer();
    // 指定目標類,即父類
    enhancer.setSuperclass(SomeService.class);
    // 設置回調接口對象
    enhancer.setCallback(this);
 
    return (SomeService) enhancer.create();
  }
 
  @Override
  public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    // 調用目標方法
    Object result = method.invoke(target, args);
    if (result != null) {
      result = ((String) result).toUpperCase();
    }
    return result;
  }
 
}

測試:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.ietree.basicskill.designpattern.dynamicproxy.cglib;
 
public class Main {
  public static void main(String[] args) {
 
    SomeService service = new MyCglibFactory().myCglibCreator();
    
    String result = service.doFirst();
    System.out.println("result = " + result);
 
    service.doSecond();
  }
}

運行結果:

?
1
2
3
執行doFirst()...
result = ABCDE
執行doSecond()...

以上這篇老生常談設計模式之動態代理就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日本 在线观看 | 特黄视频 | 黑人开嫩苞 | 欧美一级在线全免费 | 99ri国产精品 | 第一次不是你高清在线观看 | 免费理伦片高清在线 | 亚洲一区二区日韩欧美gif | 精品国产成人AV在线看 | 午夜亚洲WWW湿好爽 午夜想想爱午夜剧场 | 婷婷精品进入 | 动漫人物差差差动漫人物免费观看 | 国产精品国色综合久久 | 成年看片免费高清观看 | 福利一区二区在线观看 | avtt天堂网 手机资源 | 精品午夜中文字幕熟女人妻在线 | 国产男人搡女人免费视频 | 五月色婷婷久久综合 | 免费精品一区二区三区在线观看 | 日本人与黑人做爰视频网站 | 天天色视频 | 91精品国产综合久久香蕉 | 午夜神器18以下不能进免费 | 奇米影视在线视频 | 洗濯屋H纯肉动漫在线观看 武侠艳妇屈辱的张开双腿 午夜在线观看免费观看 视频 | 乌克兰成人性色生活片 | 网站国产| 99人中文字幕亚洲区 | 丰满大乳欲妇三级k8 | 香蕉免费一区二区三区在线观看 | 成人在线视频观看 | 免费看视频网站 | 特黄特级毛片免费视 | 国产v在线播放 | 情侣宾馆愉拍自拍视频 | 美女私人影院 | 国产亚洲精品一区二区在线观看 | 无码AV精品一区二区三区 | 亚洲一区二区福利视频 | 国产探花在线观看 |