1. 程式人生 > >Java 高新技術之動態代理

Java 高新技術之動態代理

用了一下午的時間把代理又複習了一遍,下面我對有關代理的相關知識做一下總結匯總。主要歸結為以下幾個主要問題:

1、什麼是動態代理?
2、為什麼使用動態代理?
3、使用它有哪些好處?
4、哪些地方需要動態代理?

首先,先來介紹一下代理模式

代理模式是常用的java設計模式,他的特徵是代理類與委託類有同樣的介面,代理類主要負責為委託類預處理訊息、過濾訊息、把訊息轉發給委託類,以及事後處理訊息等。代理類與委託類之間通常會存在關聯關係,一個代理類的物件與一個委託類的物件關聯,代理類的物件本身並不真正實現服務,而是通過呼叫委託類的物件的相關方法,來提供特定的服務。


按照代理的建立時期,代理類可以分為兩種。 


靜態代理:由程式設計師建立或特定工具自動生成原始碼,再對其編譯。在程式執行前,代理類的.class檔案就已經存在了。 
動態代理:在程式執行時,運用反射機制動態建立而成。 

動態代理: 

和動態代理有關的有兩個類
1.interface InvocationHandler
Object invoke(Object proxy, Method method, Object[] args)

2.class Proxy
真正表示動態代理的類,提供兩個靜態方法:


Class<?> getProxyClass(ClassLoader loader, Class<?>[] interface)


用來產生代理類,引數要提供interface陣列,它會生成這些interface的“虛擬實現”,
用來冒充真實的物件。

Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
用來產生代理物件,多了InvocationHandler引數(只是InvocationHandler介面的實現類),
它與代理物件關聯,當請求分發到代理物件後,會自動執行h.invoke(...)方法,

看完與動態代理有關的兩個類後,大致明白動態代理的含義:


A介面有c方法,類B實現A介面,原本應該是執行B類中的c方法,現在可以不這樣做;


先宣告產生B類的代理類B',由它來冒充B類的“兄弟”並“實現”A介面,
對外界來說B'應該也有c方法,可當真正呼叫它的時候,
它會去執行與它關聯InvocationHandler的invoke()方法,
在這個方法裡面你可以做很多事情。這樣,這個請求就被“代理”到其它地方去了。

下面是根據對動態代理的理解所畫出的一個原理圖 :

動態代理事例:
 

package proxy;

public interface Hello {
	//打招呼
	void sayHello(String str);  
	//列印輸出
	void print(String str); 
}

它的實現類:

package proxy;

public class HelloImpl implements Hello {

	@Override
	public void sayHello(String str) {
		// TODO Auto-generated method stub
		System.out.println("Say hello to" + str);
	}

	@Override
	public void print(String str) {
		// TODO Auto-generated method stub
		System.out.println("Print:" + str);
	}
}

下面生成與代理類相關聯的InvocationHandler物件 :

package proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class LogHandler implements InvocationHandler {
	private Object obj; 
	
	public LogHandler(Object obj) {  
		this.obj= obj;  
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// TODO Auto-generated method stub
		doBefore();  
		//在這裡可以做任何事情
		Object result = method.invoke(obj, args);  
		after();  
		return result;
	}
	
	private void doBefore() {  
		System.out.println("...before...");  
	}  
	
	private void after() {  
		System.out.println("...after...");  
	}  
}

最後編寫一個測試類,程式碼如下:

package proxy;

import java.lang.reflect.Proxy;

public class ProxyTest {

    public static void main(String[] args) {
        HelloImpl impl = new HelloImpl();
        LogHandler handler = new LogHandler(impl);
        //這裡把handler與impl新生成的代理類相關聯
        Hello hello = (Hello) Proxy.newProxyInstance(impl.getClass().getClassLoader(), 
        		impl.getClass().getInterfaces(), handler);
        
        //這裡無論訪問哪個方法,都是會把請求轉發到handler.invoke
        hello.print("正在測試");
        hello.sayHello("Chu");
    }

}

【執行結果】如下:

...before...
Print:正在測試
...after...
...before...
Say hello toChu
...after...

最後我們來回答本文開始時提出的幾個總結性問題:


1、什麼是動態代理?
一種用於轉發請求,進行特殊處理的機制,“動態”應該指的是“執行期”。


2、為什麼使用動態代理?
可以對請求進行任何處理(如事務,日誌等,這都是網上說的,我當然可以做任何處理) ;動態代理類的位元組碼在程式執行時由Java反射機制動態生成,無需程式設計師手工編寫它的原始碼。動態代理類不僅簡化了程式設計工作,而且提高了軟體系統的可擴充套件性,因為Java 反射機制可以生成任意型別的動態代理類。java.lang.reflect 包中的Proxy類和InvocationHandler 介面提供了生成動態代理類的能力。


3、使用它有哪些好處?
可以對請求進行任何處理(如事務,日誌等,這都是網上說的,我當然可以做任何處理) ;與靜態代理類對照的是動態代理類,動態代理類的位元組碼在程式執行時由Java反射機制動態生成,無需程式設計師手工編寫它的原始碼。動態代理類不僅簡化了程式設計工作,而且提高了軟體系統的可擴充套件性,因為Java 反射機制可以生成任意型別的動態代理類。java.lang.reflect 包中的Proxy類和InvocationHandler 介面提供了生成動態代理類的能力。

4.哪些地方需要,動態代理?
不允許直接訪問某些類;對訪問要做特殊處理的時候就要用到代理。

 最後的總結:

1、如果想宣告產生B類的代理類,那個B類必須要實現介面,如果沒有介面,代理類就不能偽裝成B類的“兄弟”,也就沒有存在的意思, 其實也可以偽裝成B類的“孩子”。


2、當請求代理類的方法時,這個請求會被轉到執行與代理類關聯InvocationHandler
的invoke方法。

InvocationHandler可以這樣理解:
它用來處理方法的呼叫,實現類也有同樣的意義;與代理類物件相關聯,它就是負責處理代理類應該有的動作,把所有的方法請求分發到 invoke 這個方法上。

由Proxy類的靜態方法建立的動態代理類具有以下特點:

動態代理類是public、final和非抽象型別的;
動態代理類繼承了java.lang.reflect.Proxy類;
動態代理類的名字以“$Proxy”開頭;
動態代理類實現 getProxyClass() 和 newProxyInstance() 方法中引數 interfaces 指定的所有介面;

Proxy 類的isProxyClass(Class<?> cl)靜態方法可用來判斷引數指定的類是否為動態代理類。只有通過Proxy類建立的類才是動態代理類;

動態代理類都具有一個public 型別的構造方法,該構造方法有一個InvocationHandler 型別的引數。

由Proxy類的靜態方法建立的動態代理類的例項具有以下特點:


1、假定變數foo 是一個動態代理類的例項,並且這個動態代理類實現了Foo 介面,那麼“foo instanceof Foo”的值為true。把變數foo強制轉換為Foo型別是合法的:
(Foo) foo //合法

2、每個動態代理類例項都和一個InvocationHandler 例項關聯。Proxy 類的getInvocationHandler(Object proxy)靜態方法返回與引數proxy指定的代理類例項所關聯的InvocationHandler 物件。

3、假定Foo介面有一個amethod()方法,那麼當程式呼叫動態代理類例項foo的amethod()方法時,該方法會呼叫與它關聯的InvocationHandler 物件的invoke()方法。

InvocationHandler 介面為方法呼叫介面,它聲明瞭負責呼叫任意一個方法的invoke()方法:
Object invoke(Object proxy,Method method,Object[] args) throws Throwable

引數proxy指定動態代理類例項,引數method指定被呼叫的方法,引數args 指定向被呼叫方法傳遞的引數,invoke()方法的返回值表示被呼叫方法的返回值。

相關推薦

Java 高新技術動態代理

用了一下午的時間把代理又複習了一遍,下面我對有關代理的相關知識做一下總結匯總。主要歸結為以下幾個主要問題: 1、什麼是動態代理? 2、為什麼使用動態代理? 3、使用它有哪些好處? 4、哪些地方需要動態代理? 首先,先來介紹一下代理模式 代理模式是常用的java設計模式,他的特徵是代理類與委託類

java反射動態代理學習筆記

ace ins 功能 運行 invoke -- ram lang glib 動態代理概述:代理:本來自己做的事情,請別人來做,被請的人就是代理對象;舉例:春節回家買票讓人代理買動態代理:在程序運行過程中產生的這個對象,而程序運行過程中產生對象其實就是我們剛才反射講解的內容,

黑馬程式設計師_java高新技術動態代理

                                 ----------- android培訓、java培訓、java學習型技術部落格、期待與您交流! --------- 一.代理物件存在的價值:當.class檔案 被類載入器載入 到記憶體 形成Class物件

黑馬程式設計師--高新技術動態代理

                                ------- android培訓、java培訓、期待與您交流! ---------- 一、關於動態代理的一些基本概念     在程式設計中,很多時候我們要為已存在的多個具有相同介面的目標類的各個     方法

java反射機制應用動態代理

代理類 過多 size bject interface 並且 編譯期 代理 抽象 1.靜態代理類和動態代理類區別 靜態代理:要求被代理類和代理類同時實現相應的一套接口;通過代理類的對象調用重寫接口的方法時,實際上執行的是被代理類的同樣的 方法的調用。 動態代理:在程序運

Java動態代理簡介

保留 targe tar 再次 靜態方法 idt 代碼生成 handle The 圖截於《大話設計模式》 Proxy模式是常用的設計模式,其特征是代理類與委托類有同樣的接口,代理類主要負責為委托類預處理消息、過濾消息、把消息轉發給委托類,以及事後處理消息等。 用戶

Java代理模式動態代理

    代理模式是設計模式中非常重要的一種型別。代理模式從型別上來說,可以分為靜態代理和動態代理兩種型別。     假設一個場景,有一個蛋糕店,賣的蛋糕都是用蛋糕機做的,而且不同種類的蛋糕由不同的蛋糕機來做,有水果蛋糕機,巧克力蛋糕機等。它們賣的麵包片也是麵包機做的,不同種

Java基礎加強總結動態代理(Proxy)

一、代理的概念 動態代理技術是整個java技術中最重要的一個技術,它是學習java框架的基礎,不會動態代理技術,那麼在學習Spring這些框架時是學不明白的。   動態代理技術就是用來產生一個物件的代理物件的。在開發中為什麼需要為一個物件產生代理物件呢?   舉一個現實生活中

java設計模式動態代理的概述和實現

概述 1.代理:本來應該自己做的事情,請了別人來做,被請的人就是代理物件。 舉例:春節回家買票讓人代買              2.在Java中java.lang.reflect包

反射包 java.lang.reflect⑦ Java 中 Proxy 動態代理類 探祕(三)

這個系列好久沒有續作了,你以為完了,錯了。這個動態代理有說不完的知識點,我也是在不斷的學習中才瞭解得到更多的知識。但無可否認的一點是它需更多其他的知識的支援,比如設計模式,設計思想。工作越久越覺得設計模式這個東西的重要性。  其實動態代理的前兩個例子只是簡單的列出了它的一個

4.4 Java動態代理(反射應用)

文章目錄 動態代理概述 靜態代理例項 動態代理例項 動態代理和AOP程式設計 總結 動態代理概述 由代理類決定何時及如何呼叫被代理類 被代理類要完成介面定義的功能——》建立代理類,實現介面(不同介面則

【八】Java設計模式GOF23動態代理(原生JDK和CGLIB)

一、使用JDK原生動態代理 基於Java反射機制。 Java動態代理是基於介面的,如果物件沒有實現介面則選擇用CGLIB方式實現動態代理。 實現步驟: 1.首先實現一個InvocationHandler,方法呼叫會被轉發到該類的invoke()方法。 2.然後在需要

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

具體有如下四步驟: 通過實現 InvocationHandler 介面建立自己的呼叫處理器;通過為 Proxy 類指定 ClassLoader 物件和一組 interface 來建立動態代理類;通過反射機制獲得動態代理類的建構函式,其唯一引數型別是呼叫處理器介面型別;通過建構函式建立動態代理類例項,構造時

Java設計模式Proxy動態代理

Java動態代理主要涉及到兩個類: InvocationHandler:該介面中僅定義了一個Object : invoke(Object proxy, Method method, Object[] args);引數proxy指代理類,method表示被代理的方法,args

Java基礎加強——動態代理

pack lan 自動 構造器 interface 其中 tex ide count 代理模式:   為其他對象提供一種代理以控制對這個對象的訪問。   代理模式主要分為兩類:     靜態代理:由程序員創建或特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.cl

java 1.8 動態代理源碼分析

-- sta end dem lastindex error shc 只需要 [] JDK8動態代理源碼分析 動態代理的基本使用就不詳細介紹了: 例子: class proxyed implements pro{ @Override publi

Spring AOP 動態代理實例

delete 日誌 實現類 imp exc print cati user ins 1.項目結構圖如下3.3.3.1: 圖3.3.3.1 2.IUserServ接口代碼與UserServImpl實現類代碼和上述代碼相同 3.LogHandler類代碼

JAVA靜態&動態代理

line int rgs lose 動態創建 hashcode 構造函數 super ocl 具體場景 為了使代理類和被代理類對第三方有相同的函數,代理類和被代理類一般實現一個公共的interface,該interface定義如下 public interfac

Autofac高級用法動態代理

tle ast 高級 tin options option static contain ssi 前言 Autofac的DynamicProxy來自老牌的Castle項目。DynamicProxy(以下稱為動態代理)起作用主要是為我們的類生成一個代理類,這個代理類可以在我們

java反射與動態代理的理解

system 對象的訪問 讓我 integer 打破 類屬性 全部 列表 ces 一、什麽是反射機制?   反射的官方定義是這樣的:在運行狀態中,對於任意的一個類,都能夠知道這個類的所有屬性和方法,對任意一個對象都能夠通過反射機制調用一個類的任意方法,這種動態獲取類信息及動