首页 文章资讯内容详情

java高级---->Java动态代理的原理

2026-06-01 4 花语

本文内容纲要:

-动态代理的简要说明 -一、InvocationHandler(interface)的描述: -二、Proxy(Class)的描述: -简单的Java代理 -一、先定义一个接口Interface,添加两个方法。 -二、定义一个真实的实现上述接口的类,RealObject: -三、定义一个代理对象,也实现了上述的Interface接口: -四、SimpleMain在Main方法中,测试上述的结果: -五、运行的结果如下: -Java的动态代理 -一、创建一个继承了InvocationHandler的处理器:DynamicProxyHandler -二、我们写一个测试的Main方法,DynamicProxyMain: -三、运行结果如下: -Java动态代理的原理 -一、动态代理的关键代码就是Proxy.newProxyInstance(classLoader,interfaces,handler),我们跟进源代码看看: -二、我们看一下newInstance方法的源代码: -三、当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来进行调用。 -友情链接

Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架。下面我们开始动态代理的学习。

目录导航

动态代理的简要说明 简单的Java代理 Java的动态代理 Java动态代理的原理 友情链接

动态代理的简要说明

在java的动态代理机制中,有两个重要的类或接口,一个是InvocationHandler(Interface)、另一个则是Proxy(Class)。

一、InvocationHandler(interface)的描述:

InvocationHandleristheinterfaceimplementedbytheinvocationhandlerofaproxyinstance. Eachproxyinstancehasanassociatedinvocationhandler.Whenamethodisinvokedonaproxyinstance,themethodinvocationisencodedanddispatchedtotheinvokemethodofitsinvocationhandler.

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法invoke方法:

Objectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable

这个方法接收三个参数和返回一个Object类型,它们分别代表的意思如下:

proxy:指代我们所代理的那个真实对象 method:指代的是我们所要调用真实对象的方法的Method对象 args:指代的是调用真实对象某个方法时接受的参数

返回的Object是指真实对象方法的返回类型,以上会在接下来的例子中加以深入理解。

thevaluetoreturnfromthemethodinvocationontheproxyinstance.

二、Proxy(Class)的描述:

Proxyprovidesstaticmethodsforcreatingdynamicproxyclassesandinstances,anditisalsothesuperclassofalldynamicproxyclassescreatedbythosemethods.

Proxy这个类的作用就是用来动态创建一个代理对象。我们经常使用的是newProxyInstance这个方法:

publicstaticObjectnewProxyInstance(ClassLoaderloader,Class<?>[]interfaces,InvocationHandlerh)throwsIllegalArgumentException

参数的理解:

//一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载 loader-theclassloadertodefinetheproxyclass //一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口 interfaces-thelistofinterfacesfortheproxyclasstoimplement //一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上 h-theinvocationhandlertodispatchmethodinvocationsto

返回结果的理解:一个代理对象的实例

aproxyinstancewiththespecifiedinvocationhandlerofaproxyclassthatisdefinedbythespecifiedclassloaderandthatimplementsthespecifiedinterfaces

简单的Java代理

我们创建一个Java项目用于对动态代理的测试与理解,项目结构如下:

一、先定义一个接口Interface,添加两个方法。

packagecom.huhx.proxy; publicinterfaceInterface{ voidgetMyName(); StringgetNameById(Stringid); }

二、定义一个真实的实现上述接口的类,RealObject:

packagecom.huhx.proxy; publicclassRealObjectimplementsInterface{ @Override publicvoidgetMyName(){ System.out.println("mynameishuhx"); } @Override publicStringgetNameById(Stringid){ System.out.println("argumentid:"+id); return"huhx"; } }

三、定义一个代理对象,也实现了上述的Interface接口:

packagecom.huhx.proxy; publicclassSimpleProxyimplementsInterface{ privateInterfaceproxied; publicSimpleProxy(Interfaceproxied){ this.proxied=proxied; } @Override publicvoidgetMyName(){ System.out.println("proxygetmyname"); proxied.getMyName(); } @Override publicStringgetNameById(Stringid){ System.out.println("proxygetnamebyid"); returnproxied.getNameById(id); } }

四、SimpleMain在Main方法中,测试上述的结果:

packagecom.huhx.proxy; publicclassSimpleMain{ privatestaticvoidconsume(Interfaceiface){ iface.getMyName(); Stringname=iface.getNameById("1"); System.out.println("name:"+name); } publicstaticvoidmain(String[]args){ consume(newRealObject()); System.out.println("========================================================"); consume(newSimpleProxy(newRealObject())); } }

五、运行的结果如下:

mynameishuhx argumentid:1 name:huhx ======================================================== proxygetmyname mynameishuhx proxygetnamebyid argumentid:1 name:huhx

Java的动态代理

完成了上述简单的Java代理,现在我们开始学习Java的动态代理,它比代理的思想更向前一步,因为它可以动态地创建代理并动态的处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的对策。下面我们通过案例来加深Java动态代理的理解:

一、创建一个继承了InvocationHandler的处理器:DynamicProxyHandler

packagecom.huhx.dynamicproxy; importjava.lang.reflect.InvocationHandler; importjava.lang.reflect.Method; importjava.util.Arrays; publicclassDynamicProxyHandlerimplementsInvocationHandler{ privateObjectproxied; publicDynamicProxyHandler(Objectproxied){ System.out.println("dynamicproxyhandlerconstuctor:"+proxied.getClass()); this.proxied=proxied; } @Override publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{ System.out.println("dynamicproxyname:"+proxy.getClass()); System.out.println("method:"+method.getName()); System.out.println("args:"+Arrays.toString(args)); ObjectinvokeObject=method.invoke(proxied,args); if(invokeObject!=null){ System.out.println("invokeobject:"+invokeObject.getClass()); }else{ System.out.println("invokeobjectisnull"); } returninvokeObject; } }

二、我们写一个测试的Main方法,DynamicProxyMain:

packagecom.huhx.dynamicproxy; importjava.lang.reflect.InvocationHandler; importjava.lang.reflect.Proxy; importcom.huhx.proxy.Interface; importcom.huhx.proxy.RealObject; publicclassDynamicProxyMain{ publicstaticvoidconsumer(Interfaceiface){ iface.getMyName(); Stringname=iface.getNameById("1"); System.out.println("name:"+name); } publicstaticvoidmain(String[]args)throwsException,SecurityException,Throwable{ RealObjectrealObject=newRealObject(); consumer(realObject); System.out.println("=============================="); //动态代理 ClassLoaderclassLoader=Interface.class.getClassLoader(); Class<?>[]interfaces=newClass[]{Interface.class}; InvocationHandlerhandler=newDynamicProxyHandler(realObject); Interfaceproxy=(Interface)Proxy.newProxyInstance(classLoader,interfaces,handler); System.out.println("indynamicproxyMainproxy:"+proxy.getClass()); consumer(proxy); } }

三、运行结果如下:

mynameishuhx argumentid:1 name:huhx ============================== dynamicproxyhandlerconstuctor:classcom.huhx.proxy.RealObject indynamicproxyMainproxy:classcom.sun.proxy.$Proxy0 dynamicproxyname:classcom.sun.proxy.$Proxy0 method:getMyName args:null mynameishuhx invokeobjectisnull dynamicproxyname:classcom.sun.proxy.$Proxy0 method:getNameById args:[1] argumentid:1 invokeobject:classjava.lang.String name:huhx

从以上输出结果,我们可以得出以下结论:

与代理对象相关联的InvocationHandler,只有在代理对象调用方法时,才会执行它的invoke方法 invoke的三个参数的理解:Objectproxy是代理的对象,Methodmethod是真实对象中调用方法的Method类,Object[]args是真实对象中调用方法的参数

Java动态代理的原理

一、动态代理的关键代码就是Proxy.newProxyInstance(classLoader,interfaces,handler),我们跟进源代码看看:

publicstaticObjectnewProxyInstance(ClassLoaderloader,Class<?>[]interfaces,InvocationHandlerh)throwsIllegalArgumentException{ //handler不能为空 if(h==null){ thrownewNullPointerException(); } finalClass<?>[]intfs=interfaces.clone(); finalSecurityManagersm=System.getSecurityManager(); if(sm!=null){ checkProxyAccess(Reflection.getCallerClass(),loader,intfs); } /* *Lookuporgeneratethedesignatedproxyclass. */ //通过loader和接口,得到代理的Class对象 Class<?>cl=getProxyClass0(loader,intfs); /* *Invokeitsconstructorwiththedesignatedinvocationhandler. */ try{ finalConstructor<?>cons=cl.getConstructor(constructorParams); finalInvocationHandlerih=h; if(sm!=null&&ProxyAccessHelper.needsNewInstanceCheck(cl)){ //createproxyinstancewithdoPrivilegeastheproxyclassmay //implementnon-publicinterfacesthatrequiresaspecialpermission returnAccessController.doPrivileged(newPrivilegedAction<Object>(){ publicObjectrun(){ returnnewInstance(cons,ih); } }); }else{ //创建代理对象的实例 returnnewInstance(cons,ih); } }catch(NoSuchMethodExceptione){ thrownewInternalError(e.toString()); } }

二、我们看一下newInstance方法的源代码:

privatestaticObjectnewInstance(Constructor<?>cons,InvocationHandlerh){ try{ returncons.newInstance(newObject[]{h}); }catch(IllegalAccessException|InstantiationExceptione){ thrownewInternalError(e.toString()); }catch(InvocationTargetExceptione){ Throwablet=e.getCause(); if(tinstanceofRuntimeException){ throw(RuntimeException)t; }else{ thrownewInternalError(t.toString()); } } }

三、当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来进行调用。

体现这句话的代码,我在源码中没有找到,于是我在测试类的main方法中加入以下代码:

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

这段代码的输出结果如下,与上述中调用代理对象中的getMyName方法输出是一样的,不知道Jvm底层是否是这样判断的:

dynamicproxyhandlerconstuctor:classcom.huhx.proxy.RealObject dynamicproxyname:classcom.sun.proxy.$Proxy0 method:getMyName args:nullmynameishuhxinvokeobjectisnull--------------------------------------

友情链接

测试动态代理的源代码下载访问密码7d08

本文内容总结:动态代理的简要说明,一、InvocationHandler(interface)的描述:,二、Proxy(Class)的描述:,简单的Java代理,一、先定义一个接口Interface,添加两个方法。,二、定义一个真实的实现上述接口的类,RealObject:,三、定义一个代理对象,也实现了上述的Interface接口:,四、SimpleMain在Main方法中,测试上述的结果:,五、运行的结果如下:,Java的动态代理,一、创建一个继承了InvocationHandler的处理器:DynamicProxyHandler,二、我们写一个测试的Main方法,DynamicProxyMain:,三、运行结果如下:,Java动态代理的原理,一、动态代理的关键代码就是Proxy.newProxyInstance(classLoader,interfaces,handler),我们跟进源代码看看:,二、我们看一下newInstance方法的源代码:,三、当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来进行调用。,友情链接,

原文链接:https://www.cnblogs.com/huhx/p/dynamicTheoryAdvance.html