在讲解动态代理前我们先聊聊什么是静态代理。
静态代理
假设有一天领导突发奇想,给你下发了一个需求:
统计项目中所有类的方法执行耗时。
在拿到需求的那一刻,脑海中冒出来的第一个想法是:
在每个方法的第一行和最后一行加上时间埋点,再打印一行日志不就完事了。
抄起键盘准备开干,想了想又开始犹豫了:
在每个方法都加几行代码,这不是侵入式修改吗?
听架构师大佬说这样的场景可以用代理模式,那尝试一下,具体做法如下。
静态代理的实现
(1)为工程里每个类都写一个代理类,让它与目标类实现同一个接口。图中标红色的就是代理类。
(2)在代理类里面维护一个目标实现类,调用代理类的方法时还是会去调用目标类的方法,只不过在前后加了一些其他逻辑代码。也就是说后面客户端不需要直接调用目标实现类,只需要调用代理类即可,这样就间接调用了对应方法。
用一个公式总结一下:代理类 = 增强代码 + 目标实现类 。
下面这个图中,计算耗时的逻辑就是增强代码。
(3)在所有 new 目标类的地方都替换为 new 代理类,并将目标类作为构造方法参数传入;所有使用目标类调用的地方全部都替换为代理类调用。
如果你看懂了上面的实现方法,那么恭喜你已经掌握了静态代理的核心思想。
静态代理的缺点
静态代理的思路非常简单,就是给每一个目标实现类写一个对应的代理实现类,但是如果一个项目有几千甚至有几万个类,这个工作量可想而知。
前面我们还隐藏了一个假设:每个类都会实现一个接口。那如果一个类没有实现任何接口,代理类如何实现呢?
好了,我们来总结一下静态代理的缺点:
-
静态代理需要针对每个目标实现类写一个对应的代理类,如果目标类的方法有变动,代理类也要跟着动,维护成本非常高。
-
静态代理必须依赖接口。
既然知道了静态代理的缺点,那有没有办法实现少些或者不写代理类来实现代理功能呢?答案是有,动态代理。