java代理的原理及应用
什么是代理模式?
定義
為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。在某些情況下,一個(gè)對(duì)象不適合或者不能直接引用另一個(gè)對(duì)象,而代理對(duì)象可以在客戶端和目標(biāo)對(duì)象之間起到中介的作用。
——百度百科
代理模式的角色
抽象角色:代理對(duì)象和真實(shí)對(duì)象的共同接口
代理角色:代理對(duì)象角色內(nèi)部含有對(duì)真實(shí)對(duì)象的引用,從而可以操作真實(shí)對(duì)象,同時(shí)代理對(duì)象提供與真實(shí)對(duì)象相同的接口以便在任何時(shí)刻都能夠代替真實(shí)對(duì)象。同時(shí),代理對(duì)象可以在執(zhí)行真實(shí)對(duì)象操作時(shí),附加其他的操作,相當(dāng)于對(duì)真實(shí)對(duì)象進(jìn)行封裝。
真實(shí)角色:代理角色所代表的真實(shí)對(duì)象,是我們最終要引用的對(duì)象。
示意圖
代理模式的分類(lèi)及使用
-
靜態(tài)代理
靜態(tài)代理的缺點(diǎn)很顯著,對(duì)每一個(gè)委托類(lèi)都需要?jiǎng)?chuàng)建一個(gè)代理類(lèi),為了解決這個(gè)問(wèn)題,java提供了動(dòng)態(tài)代理。
-
動(dòng)態(tài)代理
抽象角色與真實(shí)角色的定義和靜態(tài)代理完全一致,這里不再重復(fù)定義
動(dòng)態(tài)代理類(lèi)需要繼承自InvocationHandler接口,并實(shí)現(xiàn)其中的invoke方法。
1 package dynamicProxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 public class ProxyClass implements InvocationHandler { 7 8 Object subject; 9 10 public ProxyClass(Object subject) { 11 this.subject = subject; 12 } 13 14 @Override 15 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 16 System.out.println("prefix-process!"); 17 method.invoke(subject, args); 18 System.out.println("suffix-process!"); 19 return null; 20 } 21 22 } 動(dòng)態(tài)代理類(lèi) 1 package dynamicProxy; 2 3 import java.lang.reflect.Proxy; 4 5 public class DynamicProxy { 6 public static void main(String[] args) { 7 8 Subject subject = (Subject) Proxy.newProxyInstance(RealClass.class.getClassLoader(), 9 new Class[] {Subject.class}, new ProxyClass(new RealClass())); 10 11 subject.request(); 12 } 13 } 客戶端動(dòng)態(tài)代理的實(shí)現(xiàn)原理
動(dòng)態(tài)代理的實(shí)現(xiàn)主要依賴于java.lang.reflect.InvocationHandler接口與java.lang.reflect.Proxy類(lèi),其實(shí)現(xiàn)原理是基于java的反射技術(shù)。
InvocationHandler接口
動(dòng)態(tài)代理類(lèi)需要繼承自InvocationHandler接口,此接口中只包含一個(gè)方法invoke方法,接口原型如下:
1 package java.lang.reflect; 2 3 public interface InvocationHandler { 4 5 /** 6 * proxy:代表代理對(duì)象本身,用于調(diào)用本代理對(duì)象的其他方法 7 * method:代表正在被調(diào)用的委托類(lèi)的方法 8 * args:代表調(diào)用方法的參數(shù) 9 */ 10 public Object invoke(Object proxy, Method method, Object[] args) 11 throws Throwable; 12 } InvocationHandlerProxy類(lèi)
Proxy類(lèi)中定義了很多的方法,但根據(jù)上面動(dòng)態(tài)代理的應(yīng)用我們看到,最重要的一個(gè)方法就是newProxyInstance方法,該方法的作用就是動(dòng)態(tài)創(chuàng)建一個(gè)代理類(lèi)對(duì)象:
1 /** 2 * loader代表了委托類(lèi)的類(lèi)加載器 3 * interfaces代表了委托類(lèi)的接口數(shù)組 4 * h代表委托類(lèi)的實(shí)例 5 */ 6 @CallerSensitive 7 public static Object newProxyInstance(ClassLoader loader, 8 Class<?>[] interfaces, 9 InvocationHandler h) 10 throws IllegalArgumentException 11 { 12 // 判斷委托類(lèi)實(shí)例是否為空,如果未空拋異常 13 Objects.requireNonNull(h); 14 15 final Class<?>[] intfs = interfaces.clone(); 16 final SecurityManager sm = System.getSecurityManager(); 17 if (sm != null) { 18 checkProxyAccess(Reflection.getCallerClass(), loader, intfs); 19 } 20 21 /* 22 * 獲取獲取代理類(lèi)的Class實(shí)例 23 */ 24 Class<?> cl = getProxyClass0(loader, intfs); 25 26 /* 27 * Invoke its constructor with the designated invocation handler. 28 */ 29 try { 30 if (sm != null) { 31 checkNewProxyPermission(Reflection.getCallerClass(), cl); 32 } 33 34 //獲取代理類(lèi)的Constructor對(duì)象 35 final Constructor<?> cons = cl.getConstructor(constructorParams); 36 final InvocationHandler ih = h; 37 if (!Modifier.isPublic(cl.getModifiers())) { 38 AccessController.doPrivileged(new PrivilegedAction<Void>() { 39 public Void run() { 40 cons.setAccessible(true); 41 return null; 42 } 43 }); 44 } 45 46 //利用反射原理中使用constructor動(dòng)態(tài)創(chuàng)建動(dòng)態(tài)代理類(lèi)型 47 return cons.newInstance(new Object[]{h}); 48 } catch (IllegalAccessException|InstantiationException e) { 49 throw new InternalError(e.toString(), e); 50 } catch (InvocationTargetException e) { 51 Throwable t = e.getCause(); 52 if (t instanceof RuntimeException) { 53 throw (RuntimeException) t; 54 } else { 55 throw new InternalError(t.toString(), t); 56 } 57 } catch (NoSuchMethodException e) { 58 throw new InternalError(e.toString(), e); 59 } 60 } newProxyInstance動(dòng)態(tài)代理的應(yīng)用場(chǎng)景
動(dòng)態(tài)代理最著名的應(yīng)用場(chǎng)景就是spring中的aop
轉(zhuǎn)載于:https://www.cnblogs.com/qq455988971/p/8242946.html
總結(jié)
以上是生活随笔為你收集整理的java代理的原理及应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: hibernate课程 初探单表映射3-
- 下一篇: Catalan卡塔兰数