1. 程式人生 > >學習:java設計模式—動態代理模式

學習:java設計模式—動態代理模式

類定義:

1、被代理介面和實現類:Tank類實現了Moveable介面,能夠move()

package com.zec.disignmode;
public interface Moveable {
    public void move();
}

package com.zec.disignmode;
import java.util.Random;
public class Tank implements Moveable{
    @Override
    public void move() {
        System.out.println("Tank moving....");
        try {
            Thread.sleep(new Random().nextInt(10000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

2、代理加工介面和實現類:TimeHandler類實現了InvocationHandler介面,能夠invoke(Object object,Method m)在object的m方法前後加上自己記錄時間的邏輯,並不是代理類,只是提供了對被代理類的加工邏輯;

package com.zec.disignmode;
import java.lang.reflect.Method;
public interface InvocationHandler {
    public void invoke(Object o,Method m);
}

package com.zec.disignmode;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TimeHandler implements InvocationHandler{
    @Override
    public void invoke(Object object, Method m) {
        System.out.println("Time Before "+m.getName());
        try {
            m.invoke(object);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("Time After  "+m.getName());
    }

}

3、生成動態代理類的Proxy靜態類:代理產生器,根據傳進來的引數Class Intface和InvocationHandler h,產生動態代理類;從而使intface中的所有方法都加上了h中invoke方法的自定義邏輯;為了便於代理類的組合和擴充套件,代理類也會實現Intface介面,最終返回一個代理類物件;

package com.zec.disignmode;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
public class Proxy {
    public static Object newInstance(Class intface,InvocationHandler h) throws Exception {
        /*Generate the source code*/
        String rt = "\r\n";
        String methodStr = "";
        for (Method method:intface.getMethods()) {
            methodStr +=
            "    @Override"+rt+
            "    public void "+ method.getName() +"() {"+rt+
            "        try{"+rt+
            "            Method m = "+ intface.getName()+".class.getMethod(\""+ method.getName() +"\");" + rt+
            "            h.invoke(tank,m);"+rt+
            "        }catch(Exception e){e.printStackTrace();}"+rt+
            "    }"+rt
            ;
        }
        String src =
            "package com.zec.disignmode;"+rt+
            "import java.util.Random;"+rt+
            "import java.lang.reflect.*;"+rt+
            "public class TankTimeProxy implements "+ intface.getName() +"{"+rt+
            "    "+ intface.getName() +" tank;"+rt+
            "    com.zec.disignmode.InvocationHandler h;"+rt+
            "    public TankTimeProxy("+ intface.getName() +" t,com.zec.disignmode.InvocationHandler h) {"+rt+
            "        tank = t;"+rt+
            "        this.h = h;"+rt+
            "    }"+rt+
            methodStr+
            "}";
        /*Generate the java file*/
        String fileName = System.getProperty("user.dir")+"/src/com/zec/disignmode/TankTimeProxy.java";
        File f = new File(fileName);
        FileWriter fw = new FileWriter(f);
        fw.write(src);
        fw.flush();
        fw.close();
        /*Generate the class file*/
        JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager jfMgr = jc.getStandardFileManager(null, null, null);
        Iterable units = jfMgr.getJavaFileObjects(fileName);
        CompilationTask ct =  jc.getTask(null, jfMgr, null, null, null, units);
        ct.call();
        jfMgr.close();
        /*Load the class into the memory*/
        URL[] urls = new URL[]{new URL("file:/"+System.getProperty("user.dir")+"/src")};
        URLClassLoader urlLoader = new URLClassLoader(urls);
        Class c = urlLoader.loadClass("com.zec.disignmode.TankTimeProxy");
        /*Generate the object*/
        Constructor constructor = c.getConstructor(Moveable.class,InvocationHandler.class);
        Object moveable = constructor.newInstance(new Tank(),h);
        return moveable;
    }
}

4、測試類

package com.zec.disignmode;
public class Client {
    public static void main(String[] args) {
        Moveable m = new Tank();
        LogHandler h = new LogHandler();
        try {
            Moveable moveable = (Moveable) Proxy.newInstance(Moveable.class, h);
            moveable.move();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5、學習心得:

(1)為了增強代理類的可擴充套件性,代理類和被代理類實現的是同一個介面,這樣代理類可以作為被代理類再次被代理,可以實現不同功能代理的組合,本例中為Moveable;

(2)InvocationHandler介面定義了對特定物件的方法的代理加工方法,Proxy為代理生成器,newInstance(Class intface,InvocationHandler h)方法表示對intface介面的所有方法進行加工,加工的邏輯由h的invoke方法定義;

(3)代理生成器最後返回一個intface型別的引用,指向已經生成的動態代理類;

(4)對於使用者來說,不必關心動態代理類的名稱,只需要指定要代理的介面型別和處理類就可以了。

相關推薦

學習java設計模式動態代理模式

類定義: 1、被代理介面和實現類:Tank類實現了Moveable介面,能夠move() package com.zec.disignmode; public interface Moveable {     public void move(); } package co

java設計模式動態代理模式

類定義: 1、被代理介面和實現類:Tank類實現了Moveable介面,能夠move() package com.zec.disignmode; public interface Moveable { public void move(); } package com.ze

JAVA設計模式--動態代理模式

今天看了一下設計模式,下面我對這方面做個學習總結: 以小車做個例項:首先定義了一個定義了一個Moveable的介面,內的方法為move()方法;讓小車繼承Moveable介面,實現move方法,並寫了一些簡單邏輯 public void move() {        

java設定模式---代理模式--動態代理模式和cglib代理模式詳解

代理模式使用場景 代理模式的定義:什麼是代理模式呢?代理模式是常用的Java設計模式,它的特徵是代理類與委託類有同樣的介面,代理類主要負責為委託類預處理訊息、過濾訊息、把訊息轉發給委託類,以及事後處理消息等。代理類和委託類之間通常會存在關聯關係,一個代理類的物件與一個委託類的物件關聯,代理類的物

java反射實現動態代理模式

代理模式的作用是:為其他物件提供一種可以控制的訪問方式, 代理的角色: 1.抽象角色  宣告真實物件和代理物件需要實現的介面; 2.代理角色  代理物件內部含有對真實物件的引用,從而可以操縱真實的物件,同時代理物件 提供與真實物件相同的介面,以便在任何時刻都能替代真實物件,

java設計模式動態代理模式 Proxy

代理模式基本上可以理解為:本來讓A做一件事情,可以把事情交給A的代理B去處理,B不僅僅把A該做的做掉,還可以在A該做的事情的基礎上在做一些相關的事情; 所謂動態代理就是利用Java的反射機制,由程式來動態建立代理類。 一般應用場景:新增操作的log日誌,事務。。。。 1.

設計模式這是一份全面 & 清晰的動態代理模式(Proxy Pattern)學習指南

前言 今天我來全面講解Android開發中最常用的設計模式 - 代理模式中的動態代理模式 目錄 1. 為什麼要使用動態代理 1.1 背景 代理模式中的靜態代理模式存在一些特點: 1個靜態代理 只服務1種類型的目標物件 若要

設計模式代理模式靜態代理動態代理,spring aop

spring 實現接口 找到 master 代碼 -s result java 統一 代理模式分為靜態代理和動態代理。我們拿鏈家來舉例子,我們本人是真實的對象,有真實的業務需求:需要去找房子;鏈家是中介,是代理類,他來幫我執行找房子的這個操作。 靜態代理:   1.實現一個

java的三種代理模式靜態代理動態代理,cglib代理

原文:https://segmentfault.com/a/1190000011291179 一、代理模式介紹 代理模式是一種設計模式,提供了對目標物件額外的訪問方式,即通過代理物件訪問目標物件,這樣可以在不修改原目標物件的前提下,提供額外的功能操作,擴充套件目標物件的功能。 簡言之,代

設計模式學習動態代理模式

import java.lang.reflect.Method; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; class InvocationHandlerImpl implements I

Java設計模式代理模式的靜態代理動態代理

前言 代理模式分為靜態和動態。同時靜態代理又分為普通代理和強制代理。因此本文會通過示例的方式詳細介紹著三種代理模式。我們依然以網上購物為例。   普通代理 定義:要求客戶端只能訪問代理角色,而不能直接訪問真實角色。我們需要修改真實角色: 1 public class RealCon

Java設計模式代理模式動態代理

前言 什麼是動態代理呢?動態代理指的是在實現階段不需要關心代理誰,而是在執行階段才指定哪一個物件。   動態代理示例 首先要介紹一下JDK提供的一個動態代理介面 InvocationHandler。這個介面的用途在於對代理類的方法進行代理,我們先實現InvocationHandle

Java設計模式代理模式動態代理下篇

前言 上篇我們演示了使用JDK的InvocationHandler實現動態代理,本文我們採用cglib來實現動態代理。   動態代理示例 運用JDK的InvocationHandler是根據抽象介面來實現的,然而基於cglib來實現動態代理,被代理角色可以是一個普通的類,也可以是一個介面的實

JAVA設計模式-動態代理(Proxy)示例及說明

一,概念   代理設計模式的目的就是在不直接操作物件的前提下對物件進行訪問,實現這個目的得方法就是為目標物件建立一個代理(Proxy),通過代理來訪問目標物件。這個設計模式的優點是什麼呢?程式碼重用,符合開閉原則。   這樣解釋可能會不太好理解,那麼接下來就通俗的來說一下代理:   1,不知道你知不知道VP

JAVA設計模式-動態代理(Proxy)原始碼分析

在文章:JAVA設計模式-動態代理(Proxy)示例及說明中,為動態代理設計模式舉了一個小小的例子,那麼這篇文章就來分析一下原始碼的實現。 一,Proxy.newProxyInstance方法 1 @CallerSensitive 2 public static Object newProxyI

JAVA設計模式代理模式Proxy

wangking717 寫道 代理模式的作用是:為其他物件提供一種代理以控制對這個物件的訪問。在某些情況下,一個客戶不想或者不能直接引用另一個物件,而代理物件可以在客戶端和目標物件之間起到中介的作用。 或者在一系列功能模組中加入一些擴充套件的功能模組,那個時候就會用到面向切

AOP學習筆記動態代理模式

實現方法:動態代理設計模式 JDK 的動態代理:針對實現了介面的類產生代理。InvocationHandler介面 CGlib 的動態代理:針對沒有實現介面的類產生代理,應用的是底層的位元組碼增強的技術 生成當前類的子類物件,MethodInterceptor介面

Java框架學習_Mybatis(六)Mybatis的動態代理模式

之前我們為了實現資料庫操作的封裝和業務的分離,使用Dao模式,現在Mybatis提供了更加簡潔的動態代理模式,只要有介面不需要實現,就能進行資料庫操作 動態代理模式必須遵循的規範: 與表相對應的mapper配置的namespace必須是介面的全路徑名 介面的方法名

JAVA設計模式(三)靜態與動態代理模式

  代理模式:為某個物件提供一個代理,以控制對這個物件的訪問。 代理類和委託類有共同的父類或父介面,這樣在任何使用委託類物件的地方都可以用代理物件替代。代理類負責請求的預處理、過濾、將請求分派給委託類處理、以及委託類執行完請求後的後續處理。   通過上面的描述

java設計模式代理模式 (靜態&動態

  為其他物件提供一個代理控制對某個物件的訪問,代理類負責為委託類預處理訊息,過濾訊息並轉發訊息,以及進行訊息被委託類執行後的後續處理。 代理類和委託類要實現相同的介面,因為代理真正實現的還是委託類的方法。 使用場景:   如果需要委託類處理某一業務,就可以在代理類中統一處