多语言展示
当前在线:245今日阅读:167今日分享:16

java之动态代理 Dynamic Proxy

什么是是动态代理,这个词基本上从认识Java开始就听说了,可是一直没仔细研究过,之前看一点也就草草了事,今天准备详细研究一下其使用的过程,发现也没有想象中的那么困难,自己实现了一个例子,基本上就掌握了其正确的打开方式,静下心来,仔细研究。动态代理的特点:对于给定的任意一个类型的对象,都可以动态的产生一个代理对象。动态代理的应用:spring的aop。具体应用,事物控制和日志控制等。注意:被代理类必须要实现接口,因为动态代理在创建 代理类 时需要 被代理类 实现的 接口集合 作为参数。代理模式的几个角色:代理类(负责创建代理对象)、被代理类动态代理里面有两个关键词,一个是代理、另一个是动态;写过例子后发现就跟我之前了解的一样,动态代理就是根据给定的对象去创建此对象的代理对象,操作代理对象就会间接操作被代理的对象,现实生活中存在很多这样的例子,比如买房,一般都会去找代理商。今天用一个例子记录一下,假设这样一个场景:小明要买一套房,他可以自己去找房东买;也可以通过代理商去买,然后代理负责和房东联系。5java单例饿汉和懒汉模式
工具/原料

Dynamic Proxy

方法/步骤
1

动态代理中最核心的点,就是如何根据被代理的对象a,去创建代理对象:Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)这个方法就是jdk java.lang.reflect包中代理类Proxy,创建代理对象的方法。这个方法有三个参数:loader:类加载器,被代理对象的类加载器。通过反射获取 a.getClass().getClassLoader()interfaces:接口集合,被代理对象的接口集合,注意不是方法的集合。通过反射获取 a.getClass().getInterfaces()h:调用处理方法句柄。这个是一个重点,需要自己定义一个处理类H,并且实现InvocationHandler接口,此接口中有一个invoke方法。h就是这个类的实例,当我获取到代理对象后,通过代理对象调用方法时,会直接调用h的invoke方法,然后通过h的invoke方法转发到被代理对象a的相应方法。

3

(2)创建一个People类模拟一个人,小明,此类中有一个方法buyHouseByMyself,不通过代理买房子。

4

(3)创建测试类TestDynamicProxy,编写测试方法,定义一个People对象小明和一个房子对象house,然后小明去调用buyHouseByMyself方法实现买房(4)输出如下

5

编写测试类,使用动态代理(1)编写 Invocation Handler 类MyInvocationHandler,实现InvocationHandler接口,及其invoke方法。此类中有一个构造方法,其参数 target 就是 被代理对象。     Object object=method.invoke(target, args);其作用就是去调用 target对象的相应的method方法,并将方法的返回值赋给object。     因为MyInvocationHandler类的构造方法参数是Object,所以对于任何对象都可以使用此Invocation Handler 类。

6

(2)创建好了MyInvocationHandler类,就可以去获取代理对象了。编写ProxyClass类,创建一个方法getDynamicProxy获取代理对象,其参数也是一个Object,表示这个类可以获取任何对象的代理对象。在创建代理对象时,创建一个MyInvocationHandler类的实例handle,作为newProxyInstance的参数,这样通过proxy代理对象调用方法就会自动走handle的invoke方法。另外两个参数是被代理对象object的类加载器和其所实现的接口的集合。

7

(3)创建好了代理类,接着就可以测试了,我们测试通过代理去买房子。     所以在People类中添加一个方法buyHouseByDynamicProxy,其参数是House类的实例house;     然后在此方法中通过ProxyClass类获取house实例的代理对象houseProxy,接着调用buy方法。

8

(4)在TestDynamicProxy类中编写测试方法,testBuyHouseByProxy,创建一个People实例小红,调用buyHouseByDynamicProxy方法,调用动态代理购买方法。(5)查看输出,通过代理的方式,也调用到了,House中的buy方法。

9

4、思考:通过本例子可以发现,只要给定任意一个对象object,就可以调用ProxyClass的getDynamicProxy方法直接获取一个代理对象,很是方便,没必要知道此对象所属的类。         这是和静态代理相对比的,对于静态代理,需要给每个被代理类提供一个特殊的代理类,也就是一个被代理类要创建一个代理类,如果被代理类很多,这将会创建更多的类。 比如:HouseProxy;FishProxy;CarProxy类,等等,使用动态代理一个ProxyClass类,就可以解决问题了,不仅减少了类的创建,代码量也大大减少。   在本例中:小明想要买房子,小明通过代理类,找到了一个代理,代理负责去帮助小明买房子。   代理在帮助小明买房子时可以去做一些特殊的操作,就是MyInvocationHandler类invoke方法中,method.invoke方法执行前后的事情。   可想而知,通过动态代理,可以实现spring的aop:比如给某一个特定的方法开启事物或者在某一个方法调用前后打印日志。

推荐信息