您的位置:网站首页 > Java教程 > 正文

Java代理模式以及在Android上的应用

类别:Java教程 日期:2018-1-25 18:36:35 人气: 来源:

  小米近日已召开上市启动会,多个接近小米的市场人士透露,小米倾向于选择上市。但也有接近小米的手机行业人士亦称,关于上市时间和地点,小米公司内部目前暂无。

  本篇来自stormWen的,分享了一个Java代理以及在Android中的一些简单应用实现技巧,希望大家会喜欢!

  Java中的代理设计模式(Proxy),提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.代理设计模式在现实生活中无处不在,举个例子,一般明星都有个经纪人,这个经纪人的作用就是类似代理了,如果有谁想找明星,首先要通过经纪人,然后经纪人再转告明星去做某些事情,这里要注意的是:真正做事情的是明星本人,而不是经纪人,经纪人只是一个中间的角色而已,本身并不会做事情,比如唱歌是明星来唱歌,而不是经纪人来唱歌,当然了,经纪人可以做些额外的事情,比如收取一定的服务费用,然后才允许你见明星之类,这个理解很重要,因为经纪人可以做些额外的事情,这个额外的事情就为程序中提供了很多扩展的功能,下面的例子可以看到这些额外的功能,再举个例子,大家都买过房吧,一般情况下是由中介带着你去,而这个中介也是类似代理人的作用,你也要明白,真正的买房人是你,你负责出钱,中介只是负责传达你的要求而已,当然啦,一些额外的功能就是需要出点钱给中介,毕竟人家那么辛苦,坑点茶水费还是要的,大家都懂,上次在买房也被坑过一些钱,后来想起了这个代理模式,也就理解了,哈哈,大家会发现,设计模式都是源于生活,在生活中处处都有设计模式的影子,我觉得学习设计模式一定要理解,理解,理解,重要的事情说三遍。

  静态代理,指的是在编译的时候就已经存在了,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类,下面举个例子,以买房为例子。

  现在我们来弄一个中介来帮我们买房,顺便加上一些额外的功能,就是坑点我们的钱,Fuck,的中介,开玩笑,代码如下

  看到没,中介帮我们跑腿买房,被坑了10000元,结果皆大欢喜,我们买到房了,而额外功能中介也赚了点辛苦费,大家都开心,这就是静态代理的理解,可以看到,在编译时就已经决定的了.

  动态代理,顾名思义是动态的,Java中的动态一般指的是在运行时的状态,是相对编译时的静态来区分,就是在运行时生成一个代理对象帮我们干活,还是以买房为例子,如果静态代理是我们在还没有买房的时候(就是编译的时候)预先找好的中介,那么动态代理就是在买房过程中找的,注意:买房过程中说明是在买房这件事情的过程中,就是代码在运行的时候才找的一个中介,Java中的动态代理要求必须实现一个接口,InvocationHandler,动态代理也必须有一个真实的对象,不管是什么代理,只是帮忙传达指令,最终还是必须有原来的对象去干活的。

  看到没,都是需要一个真实对象的引用,然后在接口方法中做自己的逻辑,最后接口方法帮我们去实现自己的逻辑,我前面已经说过了,不管是什么代理,都是真实的对象去做行为,代理只是帮忙做事情跑腿的, 测试代码:

  可以看到运行的结果跟静态代理的是一样的,顺便提下,动态代理不仅在Java中有重要的作用,特别是AOP编程方面,更是在Android的插件话发挥了不可或缺的作用,我们前面说过Java层的Hook一般有反射和动态代理2个方面,一般情况下是成对出现的,反射是负责找出隐藏的对象,而动态代理则是生成目标接口的代理对象,然后再由反射替换掉,一起完成有意思的事情,下面我们简单来分析一下动态代理的内部原理实现:首先是生成class文件,如下代码:

  看到这里的继承关系,我想有些读者已经看懂了一个动态代理的缺陷了,因为生成的类已经有一个Proxy父类了,因此注定了不是接口的不能使用动态代理,因为java的继承机制所决定的,但通过第三方cglib可以实现,大家可以去试试,虽然有点遗憾,但不会影响其发挥的巨大作用,我们来看看是如何生成动态代理的子类,看方法:Proxy.newProxyInstance(),下面是代码:

  可以看到,是通过反射构造函数来创建子类的,而构造函数里面的参数constructorParams正是接口类型

  现在我们知道了是写到本地磁盘上的字节码,然后生成一个代理的对象,那么是如何调用具体的方法呢,在刚才那个文件ProxyClass.class告诉了我们,比如我们的接口方法:

  看到没是h来调用的,那么h从哪里来的呢?构造函数,这个构造函数就是我们代码中的 new DynamiclProxy(buy))中buy就是这里的参数var1,也就是真正需要代理的对象赋值给了父类Proxy.中的h;对象。这个类里面的其他方法的执行都是这样的流程走的,比如object类的HasCode方法等。

  看到这里,我想基本明白了吧,动态代理就一句话:系统帮我们生成了字节码文件保存在本地并生成一个InvocationHandler的代理子类,然后通过我们传进去的真实对象的引用,再帮忙调用各种接口方法,最终所有的方法都走

  从而我们可以在里面根据实际情况做不同的业务处理,比如统计耗时,替换参数(这些就是所谓的额外的功能)等等,大家有时间可以去多看那些涉及到的源码就好。

  除了提到的静态代理和动态代理,还有一种代理称为远程代理的,这个在Android比较广泛应用,特别是在IPC过程或者Binder机制中不可或缺,这种交互一般发生在不同的进程之间,所以一般称为远程代理模式。

  我们前面说了,Java中代理模式一般三种,其中动态代理用的比较多,比较灵活,而且有时候由于接口是隐藏的,也不好用静态代理,因此大多数时候都是用动态代理比较多,远程代理一般在不同进程之间使用,这里先简单介绍一下远程代理,比如我们熟悉的Activity的启动过程,其实就隐藏了远程代理的使用,由于APP本地进程和AMS(ActivityManagerService)进程分别属于不同的进程,因此在APP进程内,所有的AMS的实例其实都是经过Binder驱动处理的代理而已,大家要明白,真正的实例只有一个的,就是在AMS进程以内,其他进程之外的都不过是经过Binder处理的代理傀儡而已,还是先拿出这个启动图看看:

  可以看到APP进程和AMS进程之间可以相互调用,其实就是靠各自的远程代理对象进行调用的,而不可能之间调用(进程隔离的存在)就是APP本地进程有AMS的远端代理ActivityManagerProxy,有了这个代理,就可以调用AMS的方法了,而AMS也一样,有了ActivityThread的代理对象ApplicationThreadProxy,也可以调用APP本地进程的方法了,大家要明白,这些代理对象都是一个傀儡而已,只是Binder驱动处理之后的真实对象的引用,跟买房中介一样的性质,实际上所有Binder机制中的所谓的获取到的远程对象,都不过是远实对象的代理对象,只不过这个过程是驱动处理,对我们透明而已,有兴趣的同学可以去看看Native的源码,相信体会的更深.下面我们利用动态代理来有意义的事情。

  现在大家的项目中估计都有引入了好多个第三方的库吧,大部分是远程依赖的,有些引用库会乱发通知的,但是这些代码因为对我们不可见,为了方便对通知的统一管理,我们有必要对系统中的所有通知进行统一的控制,我们知道,通知是用NotificationManager来管理的,实际上这个不过是服务端对象在客户端对象的一个代理对象的包装,也就是说最终的管理还是在远端进程里面,客户端的作用只是包装一下参数,通过Binder机制发到服务端进行处理而已,我们先看一下代码:

  这是Binder机制的内容,首先ServiceManager通过 getService方法获取了一个原生的裸的IBinder对象,然后通过AIDL机制的asIntece方法转换成了本地的代理对象,而我们在通知中的所有的操作都是有这个sService发起的,当然了,sService也是什么事情都干不了,只是跑腿,包装参数发送给真正的远程服务对象去做真正的事情,顺便提一下,Android系统中的绝大多数服务都在以这样形式而存在的,只有少数的比如AMS,PMS是以单列形式存在,因为AMS,PMS比较常用,按照常规的套,先反射出sService字段,然后我们利用动态代理生成一个伪造的sService对象替换掉,代替我们的工作,这样所有的方法调用都会态代理的方法,这个我们前面已经说过了

  这样的话,我们就可以通过选择某些方法来做些自己想要的事情,比如判断参数,然后选择屏蔽之类,好了,我们写一波代码先:

  看到结果了吧,已经成功检测到被Hook的方法了,而具体如何执行就看具体的业务了。至此Java中的常用Hook手段:反射和动态代理就到此为止了,但实际上他们还有很多地方值得去使用,研究,只是限于篇幅,不在一一说明,以后如果有涉及到这方面的会再次提起的,大家有空可以研究源码,还是那句话,源码就是最好的学习资料

  实际上Android上的很多服务都可以用类似的手段去处理,除了在Hook之外的应用外,在动态代理里面也有广泛的应用的,在以后写性能优化的时候会提出来的,感谢大家阅读,欢迎提出改进意见,不甚感谢。

  

关键词:java安卓教程
0
0
0
0
0
0
0
0
下一篇:没有资料

网友评论 ()条 查看

姓名: 验证码: 看不清楚,换一个

推荐文章更多

热门图文更多

最新文章更多

关于联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助

郑重声明:本站资源来源网络 如果侵犯了你的利益请联系站长删除

CopyRight 2010-2012 技术支持 FXT All Rights Reserved