動態代理

来源:http://www.cnblogs.com/gdwkong/archive/2017/12/13/8035120.html
-Advertisement-
Play Games

Object proxy:當前對象,即代理對象!在調用誰的方法! Method method:當前被調用的方法(目標方法) Object[] args:實參! 案例2: ...


1、動態代理

在運行時,動態創建一組指定的介面的實現類對象!(在運行時,創建實現了指定的一組介面的對象)

interface A {}
interface B {}

Object o = 方法(new Class[]{A.class,B.class})
o它實現了A和B兩個介面!
-------------
Object proxyObject = Proxy.newProxyInstance(ClassLoader classLoader, Class[] interfaces, InvocationHandler h);
1. 方法作用:動態創建實現了interfaces數組中所有指定介面的實現類對象!
參數;
1. ClassLoader:類載入器!
* 它是用來載入器的,把.class文件載入到記憶體,形成Class對象!

2. Class[] interfaces:指定要實現的介面們
3. InvocationHandler:代理對象的所有方法(個別不執行,getClass())都會調用InvocationHandler的invoke()方法。
---------------------------------------------------------
2. 動態代理作用
最終是學習AOP(面向切麵編程),它與裝飾者模式有點相似,它比裝飾者模式還要靈活!
----------------------------------------------------------

InvocationHandler

public Object invoke(Object proxy, Method method, Object[] args);

這個invoke()方法在什麼時候被調用!在調用代理對象所實現介面中的方法時

  • Object proxy:當前對象,即代理對象!在調用誰的方法!
  • Method method:當前被調用的方法(目標方法)
  • Object[] args:實參!
----------------------------

目標對象:被增強的對象
代理對象:需要目標對象,然後在目標對象上添加了增強後的對象!
目標方法:增強的內容

代理對象 = 目標對象 + 增強

 

Waiter案例1:
 1 package demo2;
 2 
 3 import org.junit.Test;
 4 import java.lang.reflect.InvocationHandler;
 5 import java.lang.reflect.Method;
 6 import java.lang.reflect.Proxy;
 7 
 8 public class Demo2 {
 9     @Test
10     public void fun1() {
11         Waiter manWaiter = new ManWaiter();
12         /*
13         * 給出三個參數,來創建方法,得到代理對象
14         * */
15         ClassLoader loader = this.getClass().getClassLoader();
16         Class[] interfaces = {Waiter.class};
17         InvocationHandler h = new WaiterInvocationHandler(manWaiter);//參數manWaiter類表示目標對象
18         //得到代理對象,代理對象就是在目標對象的基礎上進行了增強的對象!
19         Waiter waiterProxy = (Waiter) Proxy.newProxyInstance(loader,interfaces,h);
20         waiterProxy.serve();//前面添加"你好",後面添加"再見"
21 
22     }
23 }
24 class WaiterInvocationHandler implements InvocationHandler {
25     private Waiter waiter;//目標對象
26 
27     public WaiterInvocationHandler(Waiter waiter) {
28         this.waiter = waiter;
29     }
30     @Override
31     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
32         System.out.println("您好!");
33         this.waiter.serve();//調用目標對象的目標方法
34         System.out.println("再見!");
35         return null;
36     }
37 }
1 package demo2;
2 
3 public class ManWaiter implements Waiter {
4     @Override
5     public void serve() {
6         System.out.println("服務中...");
7     }
8 }
1 package demo2;
2 
3 //服務
4 public interface Waiter {
5     //服務
6     public void serve();
7 }

 案例2:

 1 /**
 2  * 目標是讓目標對象和增強都可以切換!
 3  */
 4 public class Demo3 {
 5     @Test
 6     public void fun1() {
 7         ProxyFactory factory = new ProxyFactory();
 8         factory.setTargetObject(new ManWaiter());
 9         factory.setBeforeAdvice(new BeforeAdvice() { //設置前置增強
10             @Override
11             public void before() {
12                 System.out.println("您好!");
13             }
14         });
15         factory.setAfterAdvice(new AfterAdvice() { //設置後置增強
16             @Override
17             public void after() {
18                 System.out.println("再見!");
19             }
20         });
21 
22         Waiter waiter = (Waiter) factory.createProxy();
23         waiter.serve();
24     }
25 }
 1 package demo3;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.lang.reflect.Proxy;
 6 
 7 /**
 8  * 它用來生成代理對象
 9  * 它需要所有的參數
10  *    目標對象
11  *    增強
12  */
13 /*
14 * 1、創建代理工廠
15 * 2、給工廠設置三樣東西:
16 *   目標對象:setTargetObject(XXX);
17 *   前置增強:setBeforeAdvice(該介面的實現)
18 *   後置增強:setAfterAdvice(該介面的實現)
19 * 3、調用createProxy()得到代理對象
20 *   執行代理對象方法時:
21 *       執行BeforeAdvice的before()
22 *       目標對象的目標方法
23 *       執行AfterAdvice的after()
24 * */
25 public class ProxyFactory {
26     private Object targetObject;//目標對象
27     private BeforeAdvice beforeAdvice;//前置增強
28     private AfterAdvice afterAdvice;//後置增強
29 
30     //用來生成代理對象
31     public Object createProxy() {
32         /*
33         * 1、給出三大參數
34         * */
35         ClassLoader loader = this.getClass().getClassLoader();
36         Class[] interfaces = targetObject.getClass().getInterfaces();
37         InvocationHandler h = new InvocationHandler() {
38             @Override
39             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
40                 /*
41                 * 在調用代理對象的方法時會執行這裡的內容
42                 * */
43                 //執行前置增強
44                 if (beforeAdvice != null) {
45                     beforeAdvice.before();
46                 }
47                 Object result = method.invoke(targetObject,args);//執行目標對象的目標方法
48                 //執行後置增強
49                 if (afterAdvice != null) {
50                     afterAdvice.after();
51                 }
52                 return result;
53             }
54         };
55         //2、得到代理對象
56         Object proxObject = Proxy.newProxyInstance(loader,interfaces,h);
57         return proxObject;
58     }
59     public Object getTargetObject() {
60         return targetObject;
61     }
62     public void setTargetObject(Object targetObject) {
63         this.targetObject = targetObject;
64     }
65     public BeforeAdvice getBeforeAdvice() {
66         return beforeAdvice;
67     }
68     public void setBeforeAdvice(BeforeAdvice beforeAdvice) {
69         this.beforeAdvice = beforeAdvice;
70     }
71     public AfterAdvice getAfterAdvice() {
72         return afterAdvice;
73     }
74     public void setAfterAdvice(AfterAdvice afterAdvice) {
75         this.afterAdvice = afterAdvice;
76     }
77 }
1 /**
2  * 前置增強
3  */
4 public interface BeforeAdvice {
5     public void before();
6 }
1 /**
2  * 後置增強
3  */
4 public interface AfterAdvice {
5     public void after();
6 }

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、引用數據類型 格式:數據類型 變數名 = new 數據類型(); 每個引用類型都有自己的功能,如何使用功能? 格式:變數.方法名,如sc.nextInt(); 接收鍵盤輸入,保證輸入的是整數,否則Exception(異常) Scanner的另外一個功能 next() 接收鍵盤輸入的字元串 ①Sc ...
  • 最近在網上找到一個逆向分析挑戰的網站,http://flare-on.com/。在這裡可以下載到該網站出的一系列的逆向分析的題目,我下載了2017年的練習,總共12道題目。最近想把這些題目的結題過程寫下來,當做一些積累吧。 第一道題目是一個網頁題目,開始就給了一個login.html文件 用文本編輯 ...
  • code: RX: 解決辦法: 將第十一行的代碼改為: ...
  • 由於工作需要。記錄了使用方法。理論等在後續補充。 本人對於selenium的理解:作為python的一個第三方庫,用於Web自動化處理的工具。 一、selenium元素定位 Selenium提供了8種定位方式。 id name class name tag name link text partia ...
  • 數據類型的種類 常用的:1、數字2、字元串3、列表4、元祖5、集合 不常用的:隊列有序字典預設字典 集合的特點 1、無序 2、去重(重要) 3、可嵌套 4、關係測試(重要) 創建集合 一、創建集合的註意事項: 1、無序,不重覆的序列 2、用“{}”來代替,裡面每個元素就是一個值,跟字典的區別就是無需 ...
  • 原創不易,轉載請標明出處。上一篇《Java實驗--基於Swing的簡單的歌曲信息管理系統(一)》講解瞭如何這個小項目的具體情況和主要功能,下麵進入編碼階段。 在eclipse中新建java項目,項目的結構如下: 資料庫的設計 該項目簡單,只涉及到了兩種表,且沒有涉及到關聯查詢,就只是對單表進行操作。 ...
  • 字典的概念 字典是存儲數據的一種方式,與列表和元祖來說更靈活。元祖的局限性:值是無序,不可變的列表的局限性:如果裡面想存儲一個人的名字對應的值時dy,年齡對應的是30。使用一個列表是不行的如下: 1 >>> t=[name="dy",age=30] 2 File "<stdin>", line 1 ...
  • 本文使用python的第三方模塊requests爬取王者榮耀所有英雄的圖片,並將圖片按每個英雄為一個目錄存入文件夾中,方便用作桌面壁紙 下麵時具體的代碼,已通過python3.6測試,可以成功運行: 對於所要爬取的網頁連接可以通過王者榮耀官網找到, 下麵是保存抓取到的圖片的文件夾樣例: 以上就是抓取 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...