在讲解静态代理与动态代理的区别之前,我们先来回顾代理模式相关的知识点,往下看。
代理模式的定义
为其他对象提供一种代理以控制对这个对象的访问。
说白了,我们可以理解为生活中常见的中介或者明星经纪人,我们买房一般都会通过中介,但是最后卖房的却是开发商,可以认为中介就是开发商的代理。
代理模式的使用场景
当不能访问或不想直接访问或访问某个对象存在困难时,我们可以通过一个代理对象来间接访问,为了客户端使用的透明性,我们应该保证代理对象和被代理对象应该实现同一个接口。
静态代理
理论知识讲了一堆,有点绕口,我们直接讲静态代理吧,我们以买房为例定义接口:
1 | public interface Buy { |
小明去买房,小明也就是被代理对象:
1 | public class Xiaoming implements Buy { |
中介,也就是代理对象:
1 | public class UserProxy implements Buy { |
如上就是静态代理的实现,我们可以看到代理类是在编译期间就已经存在的,而且UserProxy代理类也只能代理实现了Buy接口的类,而动态代理与静态代理相反,通过反射机制动态的生成代理者的对象,也就是说我们在code阶段根本不需要知道代理谁,代理谁将会在执行阶段决定。
动态代理
动态代理是运行时的代理,Java实现动态代理需要实现InvocationHandler接口:
1 | public class DynamiclProxy implements InvocationHandler { |
如上代码所述,我们声明一个Object引用指向被代理的类,而我们调用被代理类的方法则是在invoke()方法里进行,是不是很简洁?也就是说我们本来交给代理类完成的事情现在完全由InvocationHandler来处理,不再关心需要代理谁,下面我们修改一下客户类的逻辑:
1 | public class ProxyClient { |
运行一下,可以发现打印是一样的。
通过上面的分析,我们可以总结下:静态代理与动态代理的区别在于代理类生成的时间不同,如果需要对多个类进行代理,并且代理的功能都是一样的,用静态代理重复编写代理类就非常的麻烦,可以用动态代理动态的生成代理类。
应用场景
动态代理不仅在Java中有重要的作用,特别是AOP编程方面,更是在Android的插件话发挥了不可或缺的作用,我们前面说过Java层的Hook一般有反射和动态代理2个方面,一般情况下是成对出现的,反射是负责找出隐藏的对象,而动态代理则是生成目标接口的代理对象,然后再由反射替换掉,一起完成有意思的事情。
下面我们来Hook Android中NotificationManagerService,直接上代码:
1 | public static void hookNotificationManager(Context context) { |
这里面有反射相关的知识,可以参考我的反射总结。
好了,我们在Application里面的attachBaseContext()方法里面注入就好,为什么要在这里注入呢,因为attachBaseContext()在四大组件中的方法是最先执行的,比ContentProvider的onCreate()方法都先执行,而ContrentProvider的onCreate()方法比Application的onCreate()都先执行,大家可以去测试一下,因此如果Hook的地方是涉及到ContentProvider的话,那么最好在这个地方执行,我们在页面发送通知试试:,代码如下:
1 | Intent intent=new Intent(); |
好了,我们看一下结果:
看到结果了吧,已经成功检测到被Hook的方法了,而具体如何执行就看具体的业务了。
参考
Java代理以及在Android中的一些简单应用
书籍 - Android设计模式