日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

JAVA基础知识之JVM-——动态代理(AOP)

發(fā)布時間:2023/12/4 综合教程 25 生活家
生活随笔 收集整理的這篇文章主要介紹了 JAVA基础知识之JVM-——动态代理(AOP) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

代理模式簡介

在很多場景下,我們想使用一個類(通常是接口)A時,并不是直接使用這個類,而是通過另外一個類B去調用A的方法,這里的類B就是一個代理類。

有很多場景都會用到這種方法,例如假如創(chuàng)建類A需要很大的開銷,我們會直接使用類B來代表類A。 又或者類A在遠程主機上,我們沒有權限直接調用A的方法,而代理類B卻有權限,我們可以調用B從而訪問到A。 又或者我們需要批量給A的方法加強一些功能,而我們沒有權限修改A,或者修改A會導致其他關聯(lián)的類因為耦合性需要修改,這時候我們也同樣可以通過代理類B來增加功能。 這種間接訪問A的方式就是一種非常常見的代理模式——通常我們只需要知道一個接口里提供了哪些方法,但并不需要方法細節(jié),我們可以通過代理類來控制這些方法的調用,并滿足例如前面提到的各種場景的功能要求。

動態(tài)代理

JAVA的代理模式大體上分為靜態(tài)代理(編譯期間就已經明確代理類及委托類的細節(jié))和動態(tài)代理(在JVM中動態(tài)生成一個代理類,通過動態(tài)生成的代理類去訪問委托類)。

動態(tài)代理也稱為AOP模式,即面向切面編程。 實現(xiàn)AOP的方式有很多,目前主要有兩種,一種是JDK自己實現(xiàn)的基于接口的動態(tài)代理,另一種是cglib方式,不需要強制實現(xiàn)接口。

本篇只簡單介紹JDK自帶的動態(tài)代理。

JDK動態(tài)代理

java動態(tài)代理主要涉及幾個角色,目標類(接口-target),代理對象(proxy),處理器類(接口-InvocationHandler)。

實現(xiàn)原理大致是這樣的,通過代理類proxy訪問目標類target時,在JDK底層,會動態(tài)生成一個proxy類(其實是子類),同時讓會讓這個proxy類實現(xiàn)target接口,這個Proxy類包含一個InvocationHandler類型的成員變量,后面就會用處理器對象去初始化這個Proxy類對象。proxy中對target類所有的方法實現(xiàn)都交給InvocationHandler的實現(xiàn)類去處理,通過在proxy中重寫target方法的實現(xiàn),而在實現(xiàn)中直接調用InvocationHandler的invoke方法,這樣就變成了我們調用代理proxy類執(zhí)行target方法的時候,實際上是執(zhí)行了InvocationHandler的invoke方法,而在invoke方法中,我們可以加入我們自己的邏輯,然后才調用真正的target中的方法。

整個過程可以用下面兩段偽代碼來模擬,

首先根據我們?yōu)閜roxy傳入的參數(target所有接口方法,InvocationHandler實例),JDK會在底層動態(tài)地為我們創(chuàng)建一個代理類,代理類如下,

 1 class Proxy0 extends Proxy  implements target {
 2 
 3   private Method m1;
 4 
 5   //用InvocationHandler去初始化proxy, 后期就可以將proxy的代理的方法交給InvocationHandler去處理
 6   public Proxy0(InvocationHandler handler) {
 7 
 8     supper(hander)
 9   }
10 
11   public void setM1(Method m1) {
12 
13     this.m1 = m1;
14   }
15 
16   private void method1(Object para) {
17 
18     this.hander.invoke(this, m1, new object[] {para});
19   }   
20 
21 }

這段代理類的動態(tài)生成過程都由JVM控制,我們不可見(當然可以通過特殊方式拿到)。可以看到代理類會實現(xiàn)目標類target的所有方法,但是實現(xiàn)類中是調用了InvocationHandler的invoke方法的,這個invoke方法是需要我們自己去實現(xiàn)的,一般類似這樣,

 1 class InvocationHandlerImpl implements InvocationHandler {
 2 private Object target; 3 @Override
 4 public Object invoke(Object proxy, Method method, Object[] args) {
 5 // 加入我們自己的代碼
 6 ....
 7 //調用目標類的真正方法
 8 method.invoke(target, args);
 9 //加入我們自己的代碼
10 .....
11 }

關鍵點在于第2行和第8行,使用了反射執(zhí)行了目標類的真正需要被代理的方法。

以上整個過程,就是proxy代理的實現(xiàn)原理。

下面這張圖片借用了別人的博客

下面是一個簡單的例子,演示JDK動態(tài)代理的用法,

定義一個Dog接口, JDK的動態(tài)代理是基于接口的,其他動態(tài)代理可以基于繼承的方式。

1 package aop;
2 
3 public interface Dog {
4     void info();
5     void run();
6 }

為接口寫個實現(xiàn)類,

 1 package aop;
 2 
 3 public class GunDog implements Dog {
 4 
 5     @Override
 6     public void info() {
 7         // TODO Auto-generated method stub
 8         System.out.println("我是一只獵狗");
 9     }
10 
11     @Override
12     public void run() {
13         // TODO Auto-generated method stub
14         System.out.println("我奔跑迅速");
15     }
16 
17 }

寫個工具類,

 1 package aop;
 2 
 3 public class DogUtil {
 4     public void method1() {
 5         System.out.println("====this is method1====");
 6     }
 7     
 8     public void method2() {
 9         System.out.println("====this is method2====");
10     }
11 }

關鍵點,寫一個處理器,實現(xiàn)InvocationHandler接口,

在invoke中加上我們自己的邏輯,再調用真正的target的方法。

后續(xù)代理類在處理target的所有方法時,都會在底層調用invoke方法,即將調用交給invoke了

 1 package aop;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 
 6 public class MyInvocationHandler implements InvocationHandler {
 7 
 8     private Object target;
 9 
10     public void setTarget(Object target) {
11         this.target = target;
12     }
13 
14     @Override
15     public Object invoke(Object proxy, Method method, Object[] args)
16             throws Throwable {
17         // TODO Auto-generated method stub
18         DogUtil du = new DogUtil();
19         du.method1();
20         Object result = method.invoke(target, args);
21         du.method2();
22         return result;
23     }
24 
25 }

寫一個工廠類獲取proxy類實例,簡化編程

 1 package aop;
 2 
 3 import java.lang.reflect.Proxy;
 4 
 5 public class MyProxyFactory {
 6     public static Object getProxy(Object target) {
 7         MyInvocationHandler handler = new MyInvocationHandler();
 8         handler.setTarget(target);
 9         return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
10     }
11 }

下面是測試類,

 1 package aop;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         Dog target = new GunDog();
 6         Dog dog = (Dog)MyProxyFactory.getProxy(target);
 7         dog.info();
 8         dog.run();
 9     }
10 }

執(zhí)行結果如下,

1 代理開始。。。
2 我是一只獵狗
3 代理結束。。。
4 代理開始。。。
5 我奔跑迅速
6 代理結束。。。

reference

http://blog.csdn.net/luanlouis/article/details/24589193

總結

以上是生活随笔為你收集整理的JAVA基础知识之JVM-——动态代理(AOP)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。