大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專(zhuān)注Java教育14年 全國(guó)咨詢/投訴熱線:400-8080-105
動(dòng)力節(jié)點(diǎn)LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁(yè) 學(xué)習(xí)攻略 Java學(xué)習(xí) Java動(dòng)態(tài)代理原理

Java動(dòng)態(tài)代理原理

更新時(shí)間:2022-05-06 10:25:00 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽1515次

動(dòng)力節(jié)點(diǎn)小編來(lái)告訴大家Java動(dòng)態(tài)代理原理是什么。Java動(dòng)態(tài)代理機(jī)制的出現(xiàn),給Java開(kāi)發(fā)者帶來(lái)了不必手工編寫(xiě)代理類(lèi),只需指定一組接口和委托類(lèi)對(duì)象,就可以動(dòng)態(tài)獲取代理類(lèi)。代理類(lèi)負(fù)責(zé)將所有的方法調(diào)用分配給委托對(duì)象進(jìn)行反射執(zhí)行,在分派執(zhí)行的過(guò)程中,開(kāi)發(fā)者還可以根據(jù)需要調(diào)整委托類(lèi)對(duì)象及其功能,這是一個(gè)非常靈活靈活的代理框架。現(xiàn)在讓我們開(kāi)始學(xué)習(xí)動(dòng)態(tài)代理。

動(dòng)態(tài)代理簡(jiǎn)述在java動(dòng)態(tài)代理機(jī)制中,有兩個(gè)重要的類(lèi)或接口,一個(gè)是InvocationHandler(Interface)、另一個(gè)是Proxy(Class)。

InvocationHandler(interface)說(shuō)明:

InvocationHandler is the interface implemented by the invocation handler of a proxy instance.
Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.

每個(gè)動(dòng)態(tài)代理類(lèi)都必須實(shí)現(xiàn) InvocationHandler 這個(gè)接口,并且代理類(lèi)的每個(gè)實(shí)例都關(guān)聯(lián)一個(gè)處理程序,當(dāng)我們通過(guò)代理對(duì)象調(diào)用一種方式時(shí),對(duì)該方法的調(diào)用會(huì)轉(zhuǎn)發(fā)到 InvocationHandler 這個(gè)接口的 invoke 方法來(lái)進(jìn)行調(diào)用. 我們來(lái)看看 InvocationHandler 做這個(gè)接口的唯一方法 invoke 方法:

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

該方法接受三個(gè)參數(shù)并返回一個(gè) Object 類(lèi)型,它們的含義如下:

proxy: 指我們所代表的真實(shí)對(duì)象 method: 指我們要調(diào)用真實(shí)對(duì)象的方法 Method object args: 指在真實(shí)對(duì)象上調(diào)用方法時(shí)接受的參數(shù) Back to Object真實(shí)對(duì)象方法的返回類(lèi)型,以上內(nèi)容將在下面的例子中進(jìn)一步理解。

the value to return from the method invocation on the proxy instance.

Proxy(Class)說(shuō)明:

Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.

Proxy 此類(lèi)用于動(dòng)態(tài)創(chuàng)建代理對(duì)象。我們經(jīng)常使用 newProxyInstance 這個(gè)方法:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

參數(shù)理解:

// One ClassLoader object , Defined by which ClassLoader Object to load the generated proxy object 
loader - the class loader to define the proxy class 
// One Interface An array of objects , What is the set of interfaces that I'm going to provide to the object that I need to proxy 
interfaces - the list of interfaces for the proxy class to implement 
// One InvocationHandler object , Represents when my dynamic proxy object is calling a method , Which one does it relate to InvocationHandler On the object 
h - the invocation handler to dispatch method invocations to

返回結(jié)果的理解:代理對(duì)象的一個(gè)??實(shí)例

a proxy instance with the specified invocation handler of a proxy class that is defined by the specified class loader and that implements the specified interfaces

普通Java代理我們創(chuàng)建一個(gè)Java項(xiàng)目用于測(cè)試和理解動(dòng)態(tài)代理,項(xiàng)目結(jié)構(gòu)如下:

1.我們定義一個(gè)接口Interface,添加兩個(gè)方法。

package com.huhx.proxy;
public interface Interface {
void getMyName();
String getNameById(String id);
}

2.定義一個(gè)實(shí)現(xiàn)上述接口的真實(shí)類(lèi),RealObject:

package com.huhx.proxy;
public class RealObject implements Interface {
@Override
public void getMyName() {
System.out.println("my name is huhx");
}
@Override
public String getNameById(String id) {
System.out.println("argument id: " + id);
return "huhx";
}./* Welcome to join java communication Q Your appearance :909038429 Blow water and chat together
}

3.... 和 、 定義一個(gè)代理對(duì)象,它也實(shí)現(xiàn)了上面的接口接口:

package com.huhx.proxy;
public class SimpleProxy implements Interface {
private Interface proxied;
public SimpleProxy(Interface proxied) {
this.proxied = proxied;
}
@Override
public void getMyName() {
System.out.println("proxy getmyname");
proxied.getMyName();
}
@Override
public String getNameById(String id) {
System.out.println("proxy getnamebyid");
return proxied.getNameById(id);
}
}

4.SimpleMain在Main方法中,測(cè)試上述結(jié)果:

package com.huhx.proxy;
public class SimpleMain {
private static void consume(Interface iface) {
iface.getMyName();
String name = iface.getNameById("1");
System.out.println("name: " + name);
}
public static void main(String[] args) {
consume(new RealObject());
System.out.println("========================================================");
consume(new SimpleProxy(new RealObject()));
}
}

5.... 和 、 運(yùn)行結(jié)果如下:

my name is huhx
argument id: 1
name: huhx
========================================================
proxy getmyname
my name is huhx
proxy getnamebyid
argument id: 1
name: huhx

Java動(dòng)態(tài)代理完成了上面簡(jiǎn)單的Java代理,現(xiàn)在我們開(kāi)始學(xué)習(xí)Java動(dòng)態(tài)代理,它比代理的思想更進(jìn)了一步,因?yàn)樗梢詣?dòng)態(tài)創(chuàng)建代理并動(dòng)態(tài)處理對(duì)代理方法的調(diào)用。在動(dòng)態(tài)代理上進(jìn)行的所有調(diào)用都被重定向到單個(gè)調(diào)用處理程序,它的工作是揭示調(diào)用的類(lèi)型并確定相應(yīng)的對(duì)策。下面我們通過(guò)案例加深對(duì)Java動(dòng)態(tài)代理的理解:

1.創(chuàng)建一個(gè)繼承 InvocationHandler 的處理器:DynamicProxyHandler

package com.huhx.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
public class DynamicProxyHandler implements InvocationHandler {
private Object proxied;
public DynamicProxyHandler(Object proxied) {
System.out.println("dynamic proxy handler constuctor: " + proxied.getClass());
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("dynamic proxy name: " + proxy.getClass());
System.out.println("method: " + method.getName());
System.out.println("args: " + Arrays.toString(args));
Object invokeObject = method.invoke(proxied, args);
if (invokeObject != null) {
System.out.println("invoke object: " + invokeObject.getClass());
} else {
System.out.println("invoke object is null");
}
return invokeObject;
}
}

2.我們寫(xiě)一個(gè)測(cè)試Main方法,DynamicProxyMain:

package com.huhx.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import com.huhx.proxy.Interface;
import com.huhx.proxy.RealObject;
public class DynamicProxyMain {
public static void consumer(Interface iface) {
iface.getMyName();
String name = iface.getNameById("1");
System.out.println("name: " + name);
}
public static void main(String[] args) throws Exception, SecurityException, Throwable {
RealObject realObject = new RealObject();
consumer(realObject);
System.out.println("==============================");
// A dynamic proxy 
ClassLoader classLoader = Interface.class.getClassLoader();
Class<?>[] interfaces = new Class[] { Interface.class };
InvocationHandler handler = new DynamicProxyHandler(realObject);
Interface proxy = (Interface) Proxy.newProxyInstance(classLoader, interfaces, handler);
System.out.println("in dynamicproxyMain proxy: " + proxy.getClass());
consumer(proxy);
}./* Welcome to join java communication Q Your appearance :909038429 Blow water and chat together
}

3. ... 和 、 運(yùn)行結(jié)果如下:

my name is huhx
argument id: 1
name: huhx
==============================
dynamic proxy handler constuctor: class com.huhx.proxy.RealObject
in dynamicproxyMain proxy: class com.sun.proxy.$Proxy0
dynamic proxy name: class com.sun.proxy.$Proxy0
method: getMyName
args: null
my name is huhx
invoke object is null
dynamic proxy name: class com.sun.proxy.$Proxy0
method: getNameById
args: [1]
argument id: 1
invoke object: class java.lang.String
name: huhx

從以上輸出,我們可以得出以下結(jié)論:

與代理對(duì)象InvocationHandler相關(guān)聯(lián),只有當(dāng)代理對(duì)象調(diào)用一個(gè)方法時(shí),才進(jìn)行invoke方法invoke 的三個(gè)參數(shù)的理解:對(duì)象代理是代理的對(duì)象,方法方法是真實(shí)對(duì)象調(diào)用的方法class , Object[] args 是真實(shí)對(duì)象中調(diào)用方法的參數(shù)

Java動(dòng)態(tài)代理的原理

1.動(dòng)態(tài)代理的關(guān)鍵代碼是Proxy.newProxyInstance(classLoader, interfaces, handler),我們跟進(jìn)源碼看看:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {
// handler Can't be empty 
if (h == null) {
throw new NullPointerException();
}
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
// adopt loader And interface , Get a proxy Class object 
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
// create proxy instance with doPrivilege as the proxy class may
// implement non-public interfaces that requires a special permission
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
return newInstance(cons, ih);
}
});
} else {
// Create an instance of the proxy object 
return newInstance(cons, ih);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
}
}

2.我們來(lái)看newInstance方法的源碼:

private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
try {
return cons.newInstance(new Object[] {h} );
} catch (IllegalAccessException | InstantiationException e) {
throw new InternalError(e.toString());
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString());
}
}
}

3....和、 當(dāng)我們通過(guò)代理對(duì)象調(diào)用一種方式時(shí),對(duì)該方法的調(diào)用轉(zhuǎn)發(fā) InvocationHandler 這個(gè)接口的 invoke 方法進(jìn)行調(diào)用。體現(xiàn)這句話的代碼,在源碼中沒(méi)有找到,所以在測(cè)試類(lèi)的main方法中添加如下代碼:

if (proxy instanceof Proxy) {
InvocationHandler invocationHandler = Proxy.getInvocationHandler(proxy);
invocationHandler.invoke(proxy, realObject.getClass().getMethod("getMyName"), null);
System.out.println("--------------------------------------");
}

這段代碼的輸出如下,而且,在上面,調(diào)用代理對(duì)象getMyName的方法輸出是一樣的,不知道!jvm 是否按此方式判斷到底:

dynamic proxy handler constuctor: class com.huhx.proxy.RealObject
dynamic proxy name: class com.sun.proxy.$Proxy0
method: getMyName
args: null
my name is huhx
invoke object is null

通過(guò)上述介紹,相信大家對(duì)Java動(dòng)態(tài)代理原理已經(jīng)有所了解,大家如果想了解更多相關(guān)知識(shí),不妨來(lái)關(guān)注一下動(dòng)力節(jié)點(diǎn)的Java在線學(xué)習(xí),里面還有更豐富的知識(shí)等著大家去學(xué)習(xí),希望對(duì)大家能夠有所幫助哦。

提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)

免費(fèi)課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 久久精品男人影院 | 99婷婷 | 99久久99这里只有免费费精品 | 国产高清精品久久久久久久 | 亚洲国产精品yw在线观看 | 一级片免费视频 | 色综合亚洲综合网站综合色 | 久久青草精品一区二区三区 | 毛片黄片一级片 | 亚洲欧美综合国产不卡 | 草草第一页 | 性孕妇video国产中国 | 亚洲欧洲视频 | 狠狠色噜噜狠狠狠狠狠色综合久久 | α片毛片 | 国产精品久久久久一区二区三区 | 欧美一级黄色片在线观看 | 91精品国产综合成人 | 欧美一级艳片视频免费观看 | 国产日产欧产精品网站 | 国产成人精品一区二区不卡 | 嫩模在线 | 伊人免费视频网 | 18禁片一级毛片视频播放免费看 | 日韩免费福利视频 | 午夜精品九九九九99蜜桃 | 亚洲日本久久一区二区va | 成人性色大片 | 日韩中文精品亚洲第三区 | 国产最新精品精品视频 | 今天的恋爱未删减在线观看 | 欧美成人高清免费大片观看 | 亚洲成人一级 | 国产目拍亚洲精品一区二区三区 | www.黄色片 | 欧美激情在线免费观看 | 二级片在线 | 国产精久久一区二区三区 | 天天色天天操天天射 | 亚州综合激情另类久久久 | 国产精品视频成人 |