色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術(shù)文章
文章詳情頁

Java動(dòng)態(tài)代理靜態(tài)代理實(shí)例分析

瀏覽:40日期:2022-09-04 13:55:29

代理模式:為其他對(duì)象提供一種代理以控制某個(gè)對(duì)象的訪問。用在:在某些情況下,一個(gè)客戶不想或者不能直接訪問另一個(gè)對(duì)象,而代理對(duì)象可以在客戶端和目標(biāo)對(duì)象之前起到中介的作用,代理對(duì)象還可以完成它附加的操作。

例子:就像房東、租客、中介的關(guān)系。中介(代理對(duì)象)為房東(真實(shí)對(duì)象)出租房子,租客(客戶)通過中介(代理對(duì)象)來找房子租房子,中介完成了租房以后可以收取中介費(fèi)(附加操作)。

先看看靜態(tài)代理模式,通過上面對(duì)代理模式的理解,可以了解到代理模式:即不直接通過new一個(gè)真實(shí)對(duì)象來調(diào)用方法,而是通過代理對(duì)象來調(diào)用一個(gè)方法,所以代理對(duì)象包含真實(shí)對(duì)象的引用。下面看一下代碼

接口:Subject包含一個(gè)方法

package com.example.designpattern.proxy; public interface Subject { void request(); }

RealSubject類,實(shí)現(xiàn)了Subject接口,為了簡單起見,方法簡單的輸出一句話:

package com.example.designpattern.proxy;public class RealSubject implements Subject {//真是角色實(shí)現(xiàn)了public void request() {System.out.println('From real subject');}}

代理類ProxySubject,也要實(shí)現(xiàn)Subject接口,實(shí)現(xiàn)Subject里面的方法,但是在這里里面是通過調(diào)用真實(shí)對(duì)象來實(shí)現(xiàn)的。

package com.example.designpattern.proxy;public class ProxySubject implements Subject {private RealSubject realSubject; //代理角色內(nèi)部引用了真實(shí)角色//代理角色實(shí)現(xiàn)目標(biāo)動(dòng)作public void request() {this.preRequest(); //在真實(shí)角色操作之前所附加的操作if (realSubject == null){realSubject = new RealSubject();}realSubject.request(); // 真實(shí)角色所完成的事情this.afterRequet(); //在真實(shí)角色操作之后附加的操作}//代理角色之前完成的動(dòng)作private void preRequest(){System.out.println('pre request');}//代理角色之后完成的動(dòng)作private void afterRequet(){System.out.println('after request');}}

客戶調(diào)用者

package com.example.designpattern.proxy;public class Client {public static void main(String[] args) {ProxySubject proxy = new ProxySubject();//通過代理對(duì)象來調(diào)用方法proxy.request(); }}

靜態(tài)代理:

可以運(yùn)行一下這些代碼哦, 可以在Client類中看到,是通過代理ProxySubject的對(duì)象proxy來調(diào)用方法的,在代理類ProxySubject中,有一個(gè)真實(shí)對(duì)象的引用,在代理對(duì)象的中request()方法調(diào)用了真實(shí)對(duì)象的方法。這樣的模式叫做代理模式。

優(yōu)點(diǎn)是:

1. 代理模式能將代理對(duì)象與真實(shí)對(duì)象被調(diào)用的目標(biāo)對(duì)象分離。

2. 一定程度上降低了系統(tǒng)的耦合度,擴(kuò)展性好。

代理類中包含了對(duì)真實(shí)主題的引用,這樣做也有缺點(diǎn):

1. 真實(shí)對(duì)象與代理類一一對(duì)應(yīng),增加真實(shí)類也要增加代理類,這樣做會(huì)快速的增加類的數(shù)量,使得系統(tǒng)變得復(fù)雜。

2. 設(shè)計(jì)代理以前真實(shí)主題必須事先存在,不太靈活。

采用動(dòng)態(tài)代理可以解決以上問題,動(dòng)態(tài)代理是相對(duì)于靜態(tài)代理來說的。

可能你也會(huì)說怎么樣實(shí)現(xiàn)動(dòng)態(tài)創(chuàng)建實(shí)例,以前我們創(chuàng)建實(shí)例不都是通過new 的方式來實(shí)現(xiàn)的嗎?

Hello hi = new Hello();

那么動(dòng)態(tài)創(chuàng)建實(shí)例是由Java提供的功能,就不需要我們?nèi)ew 對(duì)象,他已經(jīng)定義好了靜態(tài)方法Proxy.newProxyInstance(),只要傳入?yún)?shù)調(diào)用就可以。Java文檔里面有哦,如圖:

Java動(dòng)態(tài)代理靜態(tài)代理實(shí)例分析

Java標(biāo)準(zhǔn)庫提供了一種動(dòng)態(tài)代理(DynamicProxy)的機(jī)制:可以在運(yùn)行期動(dòng)態(tài)創(chuàng)建某個(gè)interface的實(shí)例。

參數(shù)解釋:

Proxy.newProxyInstance( ClassLoader loader, // 傳入ClassLoader Class<?>[] interfaces, // 傳入要調(diào)用的接口的方法數(shù)組 InvocationHandler h); //傳入InvocationHandler 的實(shí)例

下面看一下動(dòng)態(tài)代理例子代碼:

Subject 接口

package design.dynamicproxy;public interface Subject {void request(String str);}

RealSubject類 實(shí)現(xiàn) Subject 接口

package design.dynamicproxy;public class RealSubject implements Subject {@Overridepublic void request(String str) {System.out.println('From Real Subject!' + ' args:' + str );}}

動(dòng)態(tài)代理類DynamicSubject 實(shí)現(xiàn)了InvocationHandler,重寫invoke()方法

package design.dynamicproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/*** 該代理類的內(nèi)部屬性時(shí)Object類型,實(shí)際使用時(shí),使用該類的構(gòu)造方法傳遞一個(gè)對(duì)象* 此外該類還實(shí)現(xiàn)了invoke() 方法,該方法中的method.invoke() 其實(shí)就是要調(diào)用被代理對(duì)象的要執(zhí)行的方法* 方法參數(shù)是object,表示該方法從屬于object對(duì)象,通過動(dòng)態(tài)代理類,我們可以在執(zhí)行真是對(duì)象的* 方法前后可以加入一些額外的方法*/public class DynamicSubject implements InvocationHandler {//引入的類型是Object的,可以隨便傳入任何一個(gè)對(duì)象private Object object;public DynamicSubject(Object object){this.object = object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println('before calling:' + method);//等價(jià)于realSubject的request() 方法,如果這里不調(diào)用的話,不會(huì)調(diào)用Method 對(duì)象中的方法method.invoke(object, args);System.out.println('after calling:' + method);return null;}}

Client類

package design.dynamicproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class Client {public static void main(String[] args) {RealSubject realSubject = new RealSubject();InvocationHandler handler = new DynamicSubject(realSubject);Class<?> classType = handler.getClass();//下面的代碼一次性生成代理// 動(dòng)態(tài)生成了class com.sun.proxy.$Proxy0 的實(shí)例,Subject subject = (Subject) Proxy.newProxyInstance(classType.getClassLoader(), realSubject.getClass().getInterfaces(),handler);subject.request('eather');System.out.println(subject.getClass());//輸出class com.sun.proxy.$Proxy0,可以看到Proxy.newProxyInstance() 是系統(tǒng)自動(dòng)生成的實(shí)例}}

在Client中可以看到,我們這里調(diào)用方法的是 subject.request('eather'); 這個(gè)對(duì)象subject 不是通過new DynamicSubject()生成的,而是Java內(nèi)部寫好的方法在運(yùn)行時(shí)動(dòng)態(tài)生成對(duì)象;可能有人說

InvocationHandler handler = new DynamicSubject(realSubject);

這里不是通過new new DynamicSubject(realSubject); 生成了一個(gè)對(duì)象嗎? 是的,但是它是InvocationHandler 類型的,主要是傳遞一個(gè)InvocationHandler類型參數(shù)給Proxy.newProxyInstance(); 即最后一個(gè)參數(shù)。通過Client類的最后一句輸出可以看到它是 class com.sun.proxy.$Proxy0 ,這是Java運(yùn)行時(shí)生成的。

解決了靜態(tài)代理的難題:1. 真實(shí)對(duì)象與代理類一一對(duì)應(yīng),增加真實(shí)類也要增加代理類,這樣做會(huì)快速的增加類的數(shù)量,使得系統(tǒng)變得復(fù)雜。 為什么這么說呢, 因?yàn)榇眍愐玫念愋褪荗bject的,可以隨便傳入任何一個(gè)對(duì)象,當(dāng)真實(shí)類增加時(shí),代理類不用增加,new DynamicSubject(object); new的時(shí)候把要傳入的對(duì)象傳進(jìn)去即可。

下面是Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h); 這個(gè)方法的源碼啦,可以看看,深入了解一下

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{Objects.requireNonNull(h);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.生成一個(gè)代理類對(duì)象*/Class<?> cl = getProxyClass0(loader, intfs);/** Invoke its constructor with the designated invocation handler.使用指定的調(diào)用處理程序調(diào)用其構(gòu)造函數(shù)。就是使用InvocationHandler 實(shí)例調(diào)用【要調(diào)用方法的那個(gè)類】的構(gòu)造方法*/try {if (sm != null) {checkNewProxyPermission(Reflection.getCallerClass(), cl);}final Constructor<?> cons = cl.getConstructor(constructorParams);final InvocationHandler ih = h;if (!Modifier.isPublic(cl.getModifiers())) {AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() {cons.setAccessible(true);return null;}});}return cons.newInstance(new Object[]{h});}catch (IllegalAccessException|InstantiationException e) {throw new InternalError(e.toString(), e);}catch (InvocationTargetException e) {Throwable t = e.getCause();if (t instanceof RuntimeException) {throw (RuntimeException) t;} else {throw new InternalError(t.toString(), t);}}catch (NoSuchMethodException e) {throw new InternalError(e.toString(), e);}}

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 真人一级一级特黄高清毛片 | 精品视频久久久久 | 精品手机在线视频 | 一级高清毛片免费a级高清毛片 | 久久精品国产亚洲综合色 | 日韩精品中文字幕视频一区 | 日韩精品一区二区三区不卡 | 成人午夜在线视频 | 久久免费高清 | 成年人视频在线免费 | 免费观看欧美一级高清 | 亚洲精品一二三区-久久 | 欧美日韩免费做爰视频 | 免费看孕妇毛片全部播放 | 精品91一区二区三区 | 激情丝袜美女视频二区 | 国产午夜免费不卡精品理论片 | 黄色网址视频在线观看 | 国产精品久久久久免费a∨ 国产精品久久久久免费视频 | 欧美做暖小视频xo免费 | 国产综合在线观看 | 国产亚洲欧美另类久久久 | 91精品一区二区三区在线 | 免费伦费一区二区三区四区 | 精品国产免费人成高清 | 欧美精品人爱c欧美精品 | 欧美在线成人午夜网站 | 久久国产成人午夜aⅴ影院 久久国产成人亚洲精品影院老金 | 亚洲精品久久久久综合中文字幕 | 成年人黄视频在线观看 | 成人在线一区二区 | 欧美成人免费午夜影视 | 国产成人久久久精品一区二区三区 | 亚洲女精品一区二区三区 | 欧美第五页 | 欧洲女同互慰在线视频 | 欧美日韩精品一区三区 | 欧美亚洲欧美区 | 欧美日韩亚洲在线观看 | 欧美精品亚洲精品日韩 | 精品韩国主播福利视频在线观看一 |